В многомерных массивах почему разыменование адреса строки снова приводит к адресу вместо значения - PullRequest
0 голосов
/ 27 июня 2018
#include <stdio.h>

void main() {
    int a[4][3] = {
        { 3, 5, 7 },
        { 2, 4, 67 },
        { 21, 8, 9 },
        { 2, 45, 6 }
    };
    printf("%u ", *(&a[0]+1));
}

Выражение (&a[0]+1) дает &a[1], и вывод должен быть 2, но вывод кода выше &a[1] почему? Это может показаться глупым, но, пожалуйста, помогите мне.

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Выражение (&a[0]+1) дает &a[1]

Да.

и вывод должен быть 2

номер

но вывод вышеприведенного кода &a[1] почему?

Вы спрашиваете об эффекте

printf("%u ",*(&a[0]+1));

. Мы установили, что (&a[0]+1) эквивалентно &a[1]. Отсюда следует, что *(&a[0]+1) эквивалентно *(&a[1]), что, в свою очередь, эквивалентно просто a[1]. Значение a[1] представляет собой массив , а не 2, несмотря на тот факт, что 2 является значением первого элемента массива.

Ваш контекст не относится к числу тех немногих, в которых значения массива не распадаются на указатели, поэтому общий вызов функции фактически эквивалентен

printf("%u ", &a[1][0]);

Однако в этот момент мы натолкнулись на препятствие. Директива %u должна соответствовать аргументу (повышенного) типа unsigned int, а фактический аргумент вместо этого имеет тип указателя. Это несоответствие приводит к неопределенному поведению. Это правдоподобно, но отнюдь не гарантировано, что это проявляется для вас в виде печати десятичного целого числа, соответствующего части или всей битовой комбинации указателя.

Если вы хотите напечатать нулевой элемент a[1], то проще всего написать это просто как a[1][0], но вы также можете написать его как *a[1] или **&a[1] или **(&a[0] + 1) или во многих других формы.

0 голосов
/ 27 июня 2018

Как вы заметили &a[0]+1 - это &a[1]. a[1] - это массив 3 int, поэтому &a[1] - это адрес массива 3 int.

Это означает, что *&a[1] - это массив 3 int. В C массив автоматически преобразуется в адрес своего первого элемента (кроме случаев, когда он является операндом sizeof, унарным & или _Alignof или является строковым литералом, используемым для инициализации массива). Таким образом, *&a[1] автоматически становится &a[1][0].

Поскольку это указатель, его не следует печатать с %u. Правильный способ напечатать это будет:

printf("%p\n", (void *) *(&a[0]+1));

Однако, учитывая, что вы использовали %u, похоже, что произошло то, что программа напечатала значение указателя, переосмысленное как unsigned int. Это не то поведение, на которое вы должны полагаться.

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