#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
переменной.