Разница между (int *) p и & p - PullRequest
0 голосов
/ 27 октября 2018

в чем разница между утверждениями int *p = (int*) i; and int *q=&i; Вот вся программа

#include<stdio.h>
int main(){
     int i;
     int *p = (int*) i; 
     printf("\n p is %d ",p);
     int *q = &i;
     printf("\n q is %d ",q);
     return 0;
 }

полученный результат p is 22092 q is 1002476148 я думаю, что здесь и p, и q хранят адрес i, но они показывают разные значения, может кто-нибудь объяснить, почему это происходит?

Ответы [ 3 ]

0 голосов
/ 27 октября 2018

Здесь

int *p = (int*) i; /* i is not initialized */

указателю p присваивается значение i, которое является некоторыми мусорными данными и пытается преобразовать некоторые ненужные данные в тип int* и присвоить p.Если вы пытаетесь разыменовать p, это дает ошибка сегментации и вызывает неопределенное поведение .

И здесь

int *q = &i;

указатель qприсваивается действительный адрес.

Также при печати переменной указателя используйте %p вместо %d спецификатора формата, например,

 printf("\n q is %p ",(void*)q);

О присвоении целочисленных значений для указатель как int *p = (int*) i, C стандарт говорит

6.3.2.3 Указатели

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

0 голосов
/ 27 октября 2018

В соответствии со стандартом C ISO / IEC 9899: 2011, подпункт 6.3.2.3:

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

Из этого следует, что приприведение типа i к pointer-to-int, то, что оно содержит, обычно не определено.

0 голосов
/ 27 октября 2018

Первый: указатели должны быть приведены к (void*) и напечатаны с %p. %d печатает int в базе 10. То есть

#include <stdio.h>

int main(){
    int i;
    int *p = (int*) i; 
    printf("\n p is %p ", (void*)p);
    int *q = &i;
    printf("\n q is %p ", (void*)q);
}

Теперь попробуем скомпилировать программу с этими изменениями: только 2 ошибки:

% gcc ptr.c -Wall -Wextra
ptr.c: In function ‘main’:
ptr.c:5:14: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     int *p = (int*) i;
              ^
ptr.c:5:14: warning: ‘i’ is used uninitialized in this function [-Wuninitialized]
     int *p = (int*) i;
              ^~~~~~~~

Оба имеют отношение к int *p = (int*) i;; второй говорит, что используется значение i, но мы не установили никакого значения на i (это вызывает неопределенное поведение ), а другое - что мы пытаемся преобразовать целое число в указатель, и целое число не имеет такого же количества бит, как указатель на этой платформе.

1018 * Т.е. *

int *q = &i;

инициализирует указатель на int q с адресом переменной i, тогда как

int *p = (int*) i; 

интерпретирует значение мусора, содержащееся в i, в соответствии с реализацией, как адрес, и инициализирует p этим.

Не совсем равный.

...