что содержит *p?

Согласно нескольким источникам, указатель p указывает на значение, когда оно разыменовано. Таким образом, мы можем сказать, что указатель содержит адрес в качестве своего значения, и когда используется оператор разыменования (*), возвращается значение по адресу.

Указатель может быть присвоено значение следующим образом:

int a = 90; int *p = &a;

если мы назначим указатель, его значение будет следующим:

int *p; *p = 60;

60 выделяется для p и вызывает неопределенное поведение при разыменовании, поскольку 60 не является допустимым адресом. (Согласно ответу на этот вопрос).

Однако для следующего кода:

    int a = 90;
    int *p = &a;

    printf ("p is %d \n",*p);
    printf ("a is %d \n", a);
    printf ("address is %p \n",p);

    *p = 100;

    printf ("p is %d \n",*p);
    printf ("a is %d \n", a);   
    printf ("address is %p \n",p);

Получен следующий вывод:

р — 90
а — 90
адрес — 0028FED8

p равно 100
a равно 100 адрес 0028FED8

т. е. выражение *p = 100 изменяет значение в a, а не значение, содержащееся в p.

КАК ??????


person Fabulous    schedule 26.11.2016    source источник
comment
*p = &a совершенно неверно и будет отвергнуто любым приличным компилятором.   -  person gnasher729    schedule 26.11.2016
comment
а для печати адресов используйте %p, а не %d   -  person phuclv    schedule 26.11.2016
comment
Ага, отвергается. Я сделал опечатку в этом вопросе.   -  person Fabulous    schedule 26.11.2016


Ответы (4)


*p = &a даже не компилируется. p — указатель на int. В настоящее время он имеет неопределенное значение, поэтому присвоение *p чего-либо является неопределенным поведением и, скорее всего, приведет к сбою. Однако, даже если p действительно указывает на int, вы можете присвоить int только *p, &a является указателем на int, а не на int, поэтому это не компилируется.

Во втором примере *p = 60 значение p не определено, поэтому вы пытаетесь сохранить 60 в неопределенном месте в памяти. Мгновенный сбой. p не изменяется при этом, поэтому ваше объяснение неверно. p не установлен на 60. Вы не можете установить p на int. Вы можете установить его только в указатель на int.

Верный:

p = &a; 
*p = 60;
person gnasher729    schedule 26.11.2016

код, который вы написали в начале:

int *p;
int a = 90;
*p = &a;

недопустимо. Звездочка (*) в строке 1 указывает, что это указатель, а не оператор разыменования, как в строке 3.

следующий код:

int a = 90;
int *p = &a;

эквивалентно:

int a = 90;
int *p;
p = &a;

(p) является указателем и теперь указывает на адрес (a)

*p = 100;

Итак, вы просто присваиваете значение a, a = 100. и вы печатаете одно и то же значение с того же адреса.

person Liron Elimeleh    schedule 26.11.2016

Вы спросили:

т. е. выражение *p = 100 изменяет значение в a, а не значение, содержащееся в p.

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

int *p;       // Stack variable pointer to integer type w/ p's address being 4 bytes      @  0x00000000
int a = 90;   // Stack integer variable `a` and initializing it to the value of 90 located @  0x00000040 
*p = &a;      // Dereferencing the pointer `p` to be equal to the address of `a` ... One would think
              // that the address value of `a` 0x00000040 in hex would be stored into `a` which
              // has the value of 64 in decimal, however this is not always the case and this should be 
              // undefined behavior, but can still compile and run depending on the compiler and architecture. 
              // It may run or crash or not even compile or build at all. Most compilers should throw an error.

*p = 100;    // 'p' is located at 0x00000000 and contains the value 0x00000040 and by dereferencing it
             // it will assign the value of 100 to the stack address location of 0x00000040. Thus this
             // changes the value of `a` to 100

             // These two statements are in a sense equivalent  
*p = 100;    a = 100;
             // If one was to assign the address of `a` to `p` as such:
 p = &a;

ИЗМЕНИТЬ

            // Therefor the statement `*p=100` will only work if the statement
            // `p=&a` is defined and evaluated beforehand.

EDIT Теперь, что касается вопроса, основанного на заголовке: "what does *p contain?" с исходным кодом операции при условии, что *p фактически содержит мусор или то, что когда-либо было назначено ему при объявлении.

person Francis Cugler    schedule 26.11.2016
comment
› значение адреса a в шестнадцатеричном формате будет сохранено в a - person Fabulous; 26.11.2016
comment
@simrandhamija правильно, но эта строка кода имеет неопределенное поведение; и я изначально указал, что значение адреса будет храниться как шестнадцатеричное, но его эквивалентное значение в десятичном виде равно 64, поскольку тип переменной - int. Но это не то, что происходит. - person Francis Cugler; 26.11.2016
comment
разве вы не имеете в виду, что значение адреса a, которое находится в шестнадцатеричном формате, будет сохранено в p? - person Fabulous; 26.11.2016
comment
@simrandhamija да, это то, что логически произошло бы, если бы утверждение было верным, но некоторые новички могут подумать, что оно сохранит фактическое значение как его десятичное преобразование, но это не так. - person Francis Cugler; 26.11.2016
comment
@simrandhamija возьмите предложение из раздела комментариев и опустите последнюю часть with the value of 64 which is decimal, ... и просто прочитайте первую часть предложения отдельно. One would think that the address value of 'a' (0x0...) which is in hex would be stored into 'a'... - это то же самое, что вы ответили мне в своем первом и первоначальном комментарии. - person Francis Cugler; 26.11.2016

Согласно нескольким источникам, указатель p указывает на значение, когда оно разыменовано.

Не совсем. Указатель указывает на объект. Разыменование указателя создает этот объект. Использование объекта в контексте, где требуется значение, создает сохраненное значение.

int *p = &a;

Объект, на который сейчас указывает p, называется a.

*p = 100;

Разыменование p создает указанный объект, а именно a. Поскольку это не контекст, в котором требуется сохраненное значение, значение a не считывается, остается объект a, которому присвоено значение 100.

Или, проще говоря, *p означает a, поэтому *p = 100 означает a = 100.

person Community    schedule 26.11.2016
comment
поправьте меня, если я ошибаюсь, но разве C не процедурный язык? в C нет объектов, так как это не язык ООП. - person Fabulous; 26.11.2016
comment
@simrandhamija Нет, я правильно понял свою терминологию, но я понимаю, что это сбивает с толку. То, что C называет объектом, — это не то же самое, что в ООП. То, что C называет объектом, является просто блоком памяти, обычно переменной, или чем-то, на что указывает результат таких функций, как malloc. - person ; 26.11.2016