Разница между C объявлениями указателя - PullRequest
2 голосов
/ 23 февраля 2020

В чем разница между этими объявлениями?

Какое из следующих утверждений правильное и почему этот метод корректен?

int val;
int *ptr = val; // first method
int *ptr_2 = &val; // second method

Ответы [ 3 ]

3 голосов
/ 23 февраля 2020
int *ptr_2 = &val;

является правильным.

Первая часть (int *ptr_2) создает указатель на int.

Вторая часть (&val) возвращает адрес переменная val.

int *ptr = val;

присваивает значение из val ptr2.

Технически, первый из них может работать (компилятор может показывает предупреждение или ошибку приведения, см. комментарии). Если адрес хранится как целое число в val, этот адрес можно использовать таким образом, но будет бессмысленно хранить адрес в int.

Также обратите внимание, что val будет содержать случайное значение (фактически то, что было в этой точке ОЗУ), если вы его не инициализируете.

1 голос
/ 23 февраля 2020

почему первый метод неверен?

Я не уверен, что вы хотите сделать, но первый метод, вероятно, не выполняет то, что вы ожидаете .

Поэтому компилятор выдаст вам предупреждающее сообщение, если вы не напишите первый метод, подобный следующему:

int * ptr = (int *)val;

Таким образом, вы сообщаете компилятору, что знаете, что делаете и хотите компилятор ведет себя как «первый метод».

Как отметил пользователь «pmg» в своем комментарии, «первый метод» может быть полезен, если вы напрямую обращаетесь к оборудованию, такому как при программировании микроконтроллера или при разработке операционная система.

В чем отличие этих объявлений?

Давайте сделаем программу немного сложнее, чтобы увидеть, что происходит:

int val;
int hello;
int world;
int *ptr1;
int *ptr2;
int *ptr3;
int *ptr4;
int *ptr5;
int *ptr6;

val = (int)&hello; // line "1"
ptr1 = &val; // second method
ptr2 = val;  // first method (1)

val = (int)&world; // line "2"
ptr3 = &val; // second method
ptr4 = val;  // first method (2)

val = 0;
ptr5 = &val; // second method
ptr6 = val;  // first method (2)

Оператор "=" копирует значение с правой стороны в переменную с левой стороны.

&val означает: "Указатель на переменную val".

Поэтому указатель на переменную le val будет скопировано в переменные ptr1, ptr3 и ptr5, и эти три переменные-указатели будут указывать на переменную val.

Значение переменной val делает не имеет значения в этом случае.

val однако означает: «Значение переменной val».

Если мы используем 32-разрядную Windows или Linux операционной системы, мы записали адрес переменной hello в переменную val в строке, помеченной как «строка 1».

Значение val скопировано на ptr2 в строке, помеченной как «первый метод (1)», поэтому ptr2 содержит указатель на hello, а не указатель на val.

А Конечно, значение val имеет значение :

Переменная ptr4 будет содержать указатель на переменную world, а переменная ptr6 будет иметь значение NULL.

При использовании 64-битной операционной системы Windows или Linux ptr2 и ptr4 могут даже иметь недопустимые значения в примере выше.

0 голосов
/ 23 февраля 2020

То, что вы пытаетесь сделать, действует в обоих случаях, но вы не используете эту функцию правильно в 1-м случае.

int val;
int *ptr_2 = &val; // second method

Это правильно и будет работать.

Вкл. С другой стороны,

int val;
int *ptr = val; // first method

не работает. Вы пытаетесь сделать что-то вроде этого:

int val = some_integer;
int *ptr = val;

В этом случае, если some_integer может быть некоторым допустимым номером порта; вы сможете получить доступ к порту для записи / чтения, используя переменную ptr. Наиболее правильным было бы объявить ptr как volatile для этой цели. Однако такое использование указателей определяется реализацией и не переносится из одного компилятора в другой или из одной системы в другую - это полезно для встроенных систем и использования определенного компилятора. Точное определение приведения int к указателю таково:

Целое число может быть преобразовано в любой тип указателя. За исключением случаев, указанных ранее, результат определяется реализацией, может быть некорректно выровнен, может не указывать на объект ссылочного типа и может быть представлением прерывания. 56)

...