При работе с указателем на массив обнаружено неожиданное поведение - PullRequest
0 голосов
/ 22 мая 2018

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

#include<stdio.h>
int main()
{
     int (*p)[3];
     int a[3]={10,11,12};
     p=&a;
     printf("%d\n", *p[0]);
     printf("%d\n", *p[1]);
     printf("%d\n", *p[2]);
     return 0;
}

printf ("% d \ n", * p [0]);печатает 10, что ожидается.

Но printf ("% d \ n", * p [1]);не печатает 11.

И printf ("% d \ n", * p [2]);не печатает 12.

Почему?В чем причина этого?

Ответы [ 3 ]

0 голосов
/ 22 мая 2018

Приоритет оператора.[] имеет более высокий приоритет, чем *, поэтому, когда вы пишете *p[0], то же самое, что и (*(*(p + 0))) - вы делаете арифметику указателя на указателе массива.

Это означает, что, например, p[1] даетадрес p + 3*sizeof(int) байтов, который обращается к массиву за пределами.

Правильный код должен быть:

 printf("%d\n", (*p)[0]);
 printf("%d\n", (*p)[1]);
 printf("%d\n", (*p)[2]);
0 голосов
/ 22 мая 2018

int (*p)[3]; - это массив указателей на int.

int a[3]={10,11,12}; - это массив int.Массивы и указатели имеют много общих свойств.Вы можете использовать обозначение массива для указателей, например.

Давайте возьмем нормальный указатель int *p = a, который совпадает с int *p = &a[0].Теперь указатель указывает на первый элемент массива.И вы можете использовать его так же, как и массив.

 printf("%d\n", p[0]); //10
 printf("%d\n", p[1]); //11
 printf("%d\n", p[2]); //12

То, что вы сделали, получило адрес массива - «указатель», это даст адрес первого элемента массива.Потому что &a == a

Это записывается в первый элемент вашего массива указателей, оставляя вам

p[0] == a
p[1] == unknown
p[2] == unknown

, выполнив *p[0], вы получите первый элемент p (p[0])и разыменование это *.Это то же самое, что и *a или a[0].

Но, выполнив *p[1], вы попадете в неизвестную область памяти (p[1]) и отмените ее защиту *.Это неопределенное поведение.

0 голосов
/ 22 мая 2018

*p[k] равно *(p[k]), а не (*p)[k].

То, что вы получите ожидаемый результат для *p[0], можно объяснить тем, что оно совпадает с p[0][0], и это не такнезависимо от того, в каком порядке вы помещаете нули.

p[1][0] (*p[1]), однако, это не то же самое, что p[0][1] ((*p)[1]).
(Это даже не определено, так как p[1] не существует.)

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