Указатели массива, используемые в выражениях с редкими исключениями, преобразуются в указатели на свои первые элементы.
Таким образом, в этом объявлении
char ***cpp = cp;
указатель массива cp
преобразуется в указатель на его первый элемент, который определяется выражением c+3
.
В вызовах printf указатель cpp
увеличивается в два раза. Первый раз в этом вызове
printf("%s \n", **++cpp);
и второй раз в этом вызове
printf("%s \n", *--*++cpp+3);
Поэтому внутри первого вызова указатель cpp после приращения указывает на второй элемент массив cp
, то есть он указывает на элемент, инициализированный как c+2
. Таким образом, разыменовывая указатель, мы получаем указатель на строковый литерал "TEST"
, который выводится.
Во втором вызове указатель cpp
снова увеличивается. Таким образом, он указывает на элемент массива cp
, который определяется выражением c + 1
. Разыменовав этот указатель *++cpp
, мы получаем указатель со значением c + 1
. Уменьшая значение --*++cpp
, мы получаем указатель со значением c
, который указывает на первый элемент массива c
. Разыменовывая указатель мы получаем указатель на первый элемент строкового литерала "GeksQuiz"
. Теперь, добавив число 4 к указателю *--*++cpp+3
, мы получаем указатель, указывающий на четвертый символ строкового литерала. Таким образом, в этом вызове printf вывод будет "sQuiz"
Как было указано, указатель cpp теперь указывает на третий элемент массива cp после его увеличения в два раза. Таким образом, выражение cpp[-2]
возвращает первый элемент атрибута cp
со значением c+3
. Таким образом, литерал "QUIZ"
выводится в этом вызове
printf("%s \n", *cpp[-2]); // line 3
Это выражение cpp[-1]
возвращает второй элемент массива cp
, который инициализируется как c+2
. Используя выражение cpp[-1][-1]
, мы получаем указатель на второй элемент массива c, который является строковым литералом "MCQ"
, который выводится в этом вызове
printf("%s \n", cpp[-1][-1]); // line 4