Разница значений ** (ptr + 1) в char и int - PullRequest
0 голосов
/ 21 июня 2020

Пожалуйста, помогите мне, почему в приведенном ниже коде выходы разные:

int z[][3] = { 1, 2, 3, 4, 5, 6 };
printf("\n**(z+1): %d", **(z + 1));

Выход: (z+1): 4

char y[][3] = { "A", "F", "G", "J", "M", "P" };
printf("\n**(y+1): %c", **(y+1));

Выход: (y+1): F

Почему в двух вышеупомянутых выводах сначала проверяется 4-й индекс, а на втором выводе выводится 2-й индекс?

Ответы [ 3 ]

2 голосов
/ 21 июня 2020

Почему в двух приведенных выше выходных данных сначала проверяется 4-й индекс, а во втором - 2-й индекс?

Это не совсем близко к описанию происходящего.

Чтобы понять, что происходит, запишите примеры в их фактическом значении

int z[][3] = { 1, 2, 3, 4, 5, 6 };
printf("\n**(z+1): %d", **(z + 1));

на самом деле

int z[][3] = { {1, 2, 3}, {4, 5, 6} };
printf("\n**(z+1): %d", **(z + 1));

где z[0] - это массив из трех элементов, инициализированный с помощью {1, 2, 3} и z[1] - это массив из трех элементов, инициализированных с помощью {4,5,6}.

В этом z + 1 равно &z[0] + 1, что равно &z[1] (адрес массива из трех int). Итак, *(z+1) - это (ссылка на) z[1] (массив из трех элементов), а **(z+1) - это z[1][0]. Поскольку z[1] - это массив, инициализированный как элементы {4,5,6}, z[1][0] - это первый элемент этого массива. Он имеет значение 4.

Для сравнения:

char y[][3] = { "A", "F", "G", "J", "M", "P" };
printf("\n**(y+1): %c", **(y+1));

каждый из строковых литералов инициализируется как массив из двух элементов, например, "A" инициализируется как {'A', '\0'} .

Теперь y - это массив массивов из трех char. Если массиву из трех элементов задан инициализатор с двумя char, как здесь, значения, которые не инициализированы явно, инициализируются нулем. Итак,

char y[][3] = { "A", "F", "G", "J", "M", "P" };

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

char y[][3] = { {'A', '\0', '\0'}, {'F', '\0', '\0'}, {'G', '\0', '\0'}, {'J', '\0', '\0'}, {'M', '\0', '\0'}, {'P', '\0', '\0'}};

Итак, y - это массив из шести элементов, каждый из которых представляет собой массив из трех char.

Используя тот же лог c, что и в обсуждении z выше, y + 1 равно &y[1], где y[1] - это массив из трех char, который инициализируется как {'F', '\0', '\0'}. Итак, *(y + 1) - это (ссылка на) y[1], а **(y + 1) - y[1][0]. Это значение 'F'.

1 голос
/ 21 июня 2020

Если вы сделаете это

int z[][3] = { 1, 2, 3, 4, 5, 6 };
printf("\n**(z+1): %d", **(z + 1));

, вы фактически получите

int z[2][3] = { {1, 2, 3}, {4, 5, 6} };
printf("\n**(z+1): %d", **(z + 1));

С этим определением *(z+1) указывает на {4,5,6} и, следовательно, **(z+1) получает доступ к целочисленному значению 4. Вы получаете доступ к первому элементу второго элемента нашего массива.

Во второй версии это происходит:

char y[][3] = { "A", "F", "G", "J", "M", "P" };
printf("\n**(y+1): %c", **(y+1));

Это приведет к

char y[6][3] = { {'A',0,0}, {'F',0,0}, {'G',0,0}, {'J',0,0}, {'M',0,0}, {P',0,0}};
printf("\n**(y+1): %c", **(y+1));

Теперь *(y+1) указывает на {'F',0,0} и, следовательно, **(y+1) получает доступ к символьному значению 'F'. Вы получаете доступ к первому элементу второго элемента нашего массива.

Фактически, это тот же результат, что и в первой версии.

0 голосов
/ 21 июня 2020

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

Как здесь:

char y[] = { 'A', 'F', 'G', 'J', 'M', 'P' };
printf("\n**(y+1): %c", *(y + 1));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...