Программа продолжает сбой при отработке использования указателя в функции printf

#c

#c

Вопрос:

Я новичок в программировании. Я пытаюсь запустить эту чрезвычайно простую программу в качестве практики для интеграции указателей в мой код. Когда я запускаю программу, она вылетает при запуске с Windows has encountered an unexpected error всплывающим окном. Для самого кода не выдается абсолютно никаких ошибок, но всплывающее окно сохраняется.

Я пока запускаю код в Code:: Blocks, и программа выдает указанное всплывающее окно из Windows при запуске. Я также тестировал программу на codepad.org и единственное сообщение об ошибке, которое появляется, связано с первой строкой (оператор include). Ошибка гласит: Segmentation fault .

 #include <stdio.h>
int main() {
    // Setting a variable to store the value 15.
    unsigned short int random_number = 15;
    // Defining my pointer.
    unsigned short int *number_pointer;
    // Setting the pointer to hold the memory address of my first variable.
    number_pointer = random_number;
    // Attempting to print the value at the memory address stored in the pointer.
    printf("This code will now print a number: %i", *number_pointer);
    return 0;
}
  

Я ожидаю, что результат будет: This code will now print a number: 15. , однако я даже не получил результат из-за сбоя программы.

Комментарии:

1.Вашей первой задачей сейчас было бы выяснить, куда идут диагностические данные компилятора, и прочитать их! Кроме того, возможно, потребуется напечатать беззнаковый short int с помощью, %hu но %i это тоже может сработать, а может и не,, работать…

Ответ №1:

Здесь

 number_pointer = random_number;
  

number_pointer имеет тип указателя, и он должен инициализироваться некоторым допустимым адресом, а не некоторым значением. Фактически приведенное выше утверждение заставляет компилятор предупреждать вас, как

предупреждение: несовместимое преобразование целого числа в указатель, присваивающее ‘unsigned short *’ из ‘unsigned short’; принимайте адрес с помощью amp; [-Wint-conversion]

но вы, кажется, проигнорировали это. Никогда не игнорируйте предупреждения компилятора. Всегда компилируйте код с минимальными предупреждающими флагами, такими как -Wall amp; прочитайте эти предупреждения. например,

 gcc -Wall -Wextra -Wpedantic -Werror test.c  
  

number_pointer Необходимо указывать на адрес random_number , чтобы вы могли отменить ссылку на него, как *number_pointer .

Это должно быть

 number_pointer = amp;random_number; /* assign the address of random_number */
  

Ответ №2:

Комментарий

 // Setting the pointer to hold the memory address of my first variable.
  

кажется правильным, но прокомментированный код не:

 number_pointer = random_number;
  

random_number это число, number_pointer это указатель.
Число и указатель — это разные типы, и компилятор должен предупредить вас, что это несовместимые типы.

Присвоение значения переменной несовместимого типа приводит к потере данных (когда тип переменной использует меньше байтов, чем тип значения). Но главная опасность, когда назначаются данные несовместимых типов, заключается в повреждении данных.

В вашем случае значение number_pointer ( 15 , которое является числом) сохраняется в переменной random_pointer . Когда используется значение random_pointer , 15 интерпретируется как указатель, то есть адрес в памяти, и это совершенно неправильно.

Затем выражение *number_pointer пытается прочитать память по этому адресу, и это приводит к ошибке доступа, которая наказывается операционной системой (которая завершает работу вашей программы).

Источником проблемы является отсутствие amp; (оператора «address of») перед random_number в приведенном выше присваивании. Оно должно гласить:

 number_pointer = amp;random_number;
  

Это означает, что переменная number_pointer (типа «указатель на int») будет хранить адрес переменной random_number (типа «int»). Они совместимы, и логика программы верна. Затем с помощью оператора разыменования ( * ) успешно считывается целочисленное значение, сохраненное по адресу, сохраненному в number_ponter переменной.