av [1] и av [1] [0] Не один и тот же адрес? - PullRequest
0 голосов
/ 02 мая 2020

Что случилось? Я не могу понять эту проблему ... Я знаю, что первый элемент массива содержит адрес всего массива. Но в этой ситуации я не могу понять это.

#include <stdio.h>

int main(int ac, char **av)
{
    printf("&av[1]= %p\n", &av[1]);
    printf("&av[1][0]= %p\n", &av[1][0]);

    return(0);
}

Вход

./a.out "Hello"

Выход

&av[1]= 0x7ffee0ffe4f0
&av[1][0]= 0x7ffee0ffe778

Ответы [ 4 ]

2 голосов
/ 02 мая 2020

Если кто-то сказал вам, что char **av объявляет двумерный массив, он оказал вам медвежью услугу. В char **av, av - указатель на char *, возможно, первый char * из нескольких. Таким образом, av[1] является char * - это указатель на char, а &av[1] является адресом этого указателя .

av[1][0] - это char, на который указывает av[1], а &av[1][0] - это адрес этого char.

. Указатель на char и char, конечно, не то же самое место, поэтому &av[1] и &av[1][0] различны.

В отличие от этого, если у вас был массив, такой как char av[3][4], то av - это массив из 3 массивов 4 char. В этом случае av[1] является массивом 4 char, а &av[1] будет адресом (началом) этого массива. &av[1][0] будет адресом первого char в этом массиве. Поскольку char находится в начале массива, адрес массива и адрес char совпадают.

(Однако они не обязательно представлены одинаково в C реализация, и печать их с помощью %p может показать разные результаты, даже если они ссылаются на одно и то же место в памяти.)

1 голос
/ 04 мая 2020

av - указатель на массив указателей на char с. Таким образом, его второй элемент (второй элемент массива) действительно является указателем. &av[1] это его адрес (адрес указателя, а не адрес символа).

С другой стороны, av[1][0] - это первый символ этой второй строки. Его адрес - char адрес, где хранится первый символ.

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

av[1] и &av[1][0] - это, соответственно, значение указателя (которое указывает на первый символ) и адрес первого символа второй строки, поэтому они должны быть указателями, показывающими одно и то же значение . То же самое происходит с *av[1] и av[1][0], они представляют одинаковые указатели на символы.

1 голос
/ 02 мая 2020

av - это массив указателей, где каждый элемент этого массива указывает на char array (типа char *), в котором хранится каждый символ, который вы передаете в качестве ввода в программу.

Как видно из следующего варианта вашей программы, av[0] хранит адрес av[0][0] (т.е. указывает на первую позицию строки, хранящейся в av[0][0]), которая содержит символ . и av[1] хранит адрес av[1][0] (т.е. указывает на первую позицию строки, хранящейся в av[1][0]), которая содержит символ H.

#include <stdio.h>

int main(int ac, char **av)
{

    printf("&av[0]= %p\n", &av[0]);
    printf("&av[1]= %p\n", &av[1]);

    printf("av[0]= %p\n", av[0]);
    printf("av[1]= %p\n", av[1]);

    printf("av[0][0]= %c\n", av[0][0]);
    printf("av[0][1]= %c\n", av[0][1]);


    printf("av[0][0]= %p\n", &av[0][0]);
    printf("av[0][1]= %p\n", &av[0][1]);

    printf("av[1][0]= %c\n", av[1][0]);
    printf("av[1][1]= %c\n", av[1][1]);

    printf("av[1][0]= %p\n", &av[1][0]);
    printf("av[1][1]= %p\n", &av[1][1]);

    return(0);
}

, который обеспечивает следующий вывод :

$ ./a.out "Hello"
&av[0]= 0x7fff53625cf8
&av[1]= 0x7fff53625d00

av[0]= 0x7fff53626ee9
av[1]= 0x7fff53626ef1

av[0][0]= .
av[0][1]= /
&av[0][0]= 0x7fff53626ee9
&av[0][1]= 0x7fff53626eea

av[1][0]= H
av[1][1]= e
&av[1][0]= 0x7fff53626ef1
&av[1][1]= 0x7fff53626ef2

Графически это что-то вроде (значительная часть адресов была удалена в целях упрощения):

      av: | 26ee9 | 26ef1 |
              |       |
            av[0]   av[1] 
 address:   25cf8   25d00

   av[0]: |   .  |    /   | ...
              |       |
          av[0][0] av[0][1] 
 address:   26ee9   26eea

   av[1]: |   H  |    e   | ...
              |       |
          av[1][0] av[1][1] 
 address:   26ef1   26ef2

Надеюсь это проясняет ваши сомнения.

1 голос
/ 02 мая 2020

av здесь не является двумерным массивом. Это массив указателей.

В то время как с двумерным массивом &av[1][0] будет иметь тот же адрес, что и &av[1]; в массиве указателей &av[1][0] означает, что нужно взять второй (index = 1) указатель, разыменовать его и дать мне адрес первого элемента, на который указывает цель разыменованного указателя (цель av[1] также является указатель).

&av[1] - это адрес второго char*, &av[1][0] - это адрес первого символа, на который указывает второй char*. Разные вещи.

...