Почему & p и & a [0] отличаются? - PullRequest
0 голосов
/ 02 октября 2018
#include <stdio.h>

int main(void) {
    int a[4][2] = { {11, 12}, {21, 22}, {31, 32}, {41, 42} };
    int *p = a[0];

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

    printf("%d\n", p); 

    printf("%d\n", a[0]);

    printf("%d\n", &p);

    printf("%d\n", &a[0]);

    printf("%d\n", a); 

    return 0;
}

Посмотрите на приведенный выше код.

В моем понимании, поскольку p равно a[0], &p и &a[0] должны иметь одинаковое значение.

Но фактический результат выглядит следующим образом:

11
1772204208
1772204208
1772204200
1772204208
1772204208

Почему &p и &a[0] различны?

Что представляет собой &p?

Ответы [ 6 ]

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

В C "&" означает "адрес". Это означает, что & p означает адрес p. Следует помнить, что указатель - это также переменная, которая может хранить адрес другой переменной.объявляется новая переменная, она будет выделять другое место в памяти (адрес) для этой переменной для хранения значения этой переменной. Так что значение переменной отличается от адреса переменной. В вашем коде и [0], и p являются разными переменными.Таким образом, оба имеют разные области памяти.

, поэтому постарайтесь понять следующее

int * p = a [0];Приведенная выше строка означает, что адрес a [0] сохраняется в переменной p. Это означает, что значение p - это адрес a [0]. Поэтому p равно & a [0].

Теперьрассмотрите следующий код (не в вашем коде) int ar [10];int * k = ar;Вышеприведенные две строки кода являются допустимым кодом на языке C. Рассмотрим вторую строку кода. Поскольку ar присваивается значение k, нам нужно понять одну вещь: обе переменные одного типа. Это означает, что ar также является указателем. Ar представляетадрес первого элемента в массиве ar, т. е. a [0] .it означает, что ar и & a [0] оба одинаковы.Если мы свяжем все вышеперечисленное с вашим кодом, мы заключим, что

& a [0], p, a одинаковы и представляют один и тот же адрес.* p, a [0] - это значения, которые представляют значение первого элемента в массиве.

Надеюсь, это поможет вам ...

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

В моем понимании, поскольку p равно [0], & p и & a [0] должны иметь одинаковое значение.

p и a[0] действительно имеютодинаковое значение, но это не значит, что они идентичны.Также как если у вас есть 2 переменные i и j, определенные как int i = 0, j = 0;, это правда, что i и j имеют одно и то же значение, но, очевидно, имеют разные адреса.

Обратите внимание, что вашкод имеет неопределенное поведение, потому что %d не является подходящим спецификатором преобразования для указателя на int.Вы должны %p и передать указатель на (void*) или %llu и указатель на (unsigned long long)(uintptr_t)p.uintptr_t определено в <stdint.h>.

Вот исправленная версия:

#include <stdio.h>

int main(void) {
    int a[4][2] = { {11, 12}, {21, 22}, {31, 32}, {41, 42} };
    int *p = a[0];

    printf("   *p: %d\n", *p);
    printf("    p: %p\n", (void*)p); 
    printf(" a[0]: %p\n", (void*)a[0]);
    printf("   &p: %p\n", (void*)&p);
    printf("&a[0]: %p\n", (void*)&a[0]);
    printf("    a: %p\n", (void*)a); 
    return 0;
}

Вывод:

   *p: 11
    p: 0x7fff5144d950
 a[0]: 0x7fff5144d950
   &p: 0x7fff5144d948
&a[0]: 0x7fff5144d950
    a: 0x7fff5144d950

Как видите, массив a имеет тот же адрес, что и его первая строка a[0], и это также адрес a[0][0], на который указывает p.

&a[0] отличается от a[0]: тот же адрес, но отличаетсятип: a[0] - это массив 2 int, &a[0] - это адрес массива 2 int.&a[0] + 1 указывает на a[1], тогда как a[0] + 1 указывает на a[0][1].

Извините, я не могу объяснить это в более простых терминах, очень сложно принять адрес массива: вы можетедостичь довольно продвинутого уровня программирования на C без необходимости понимать эти тонкости.Просто помните, что массивы затухают как указатели на их первый элемент в большинстве контекстов выражений (кроме как в качестве аргумента для sizeof) и никогда не используют оператор addressof (&) для массива.

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

p - это указатель, указывающий на массив a[0]:

int *p = a[0];

Просмотр в памяти будет выглядеть примерно так:

        a[0][0] a[0][1]
        +-------------+
   a[0] |  11  |  12  |
        +-------------+
        ^
        |
        p

Из этого ясно, чточто p и a[0] являются одним и тем же указателем, но &p и &a[0] отличаются.

Примечание:
%d не является правильным спецификатором формата для печати указателя.Вместо этого вы должны использовать %p.

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

p Указатель на целое число.Он хранится в адресе, а также хранит адрес.

При печати p будет напечатан адрес p, указывающий на.

При печати *p печатается значение p, указывающее на.

Печать &p печатаетсяадрес p, который является уникальным для p и был назначен в момент его объявления.

int *p_2 = &p;

p_2 будет иметь то же значение, что и &p

Каждая переменная имеет свой уникальный адрес!

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

p - указатель, который является переменной, содержащей адрес памяти.

Оператор & дает адрес объекта, на котором вы его используете, поэтому &p означает адрес указателя.

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

&p дает адрес указателя p, который, очевидно, должен отличаться от адреса a[0].

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