#cpp #c
int main()
{
char *c[] = {"ENTER", "NEW", "POINT", "FIRST"};
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;
printf("%s", **++cpp);
printf("%s", *--*++cpp+3);
printf(" %s", *cpp[-2]+3);
printf("%s", cpp[-1][-1]+1);
system("pause");
return 0;
}
Объясните пожалуйста почему вывод: POINTER STEW
На уроке не объяснили толком ничего про указатели, ни инкремент, ни дикремент.
Также не понимаю почему код printf("%s", *(c+1)); компилится, а
printf("%s", *++c); не компилится.
Ответы
Ответ 1
//массив указателей на строковые константы char *c[] = {"ENTER", "NEW", "POINT", "FIRST"}; char **cp[] = {c+3, c+2, c+1, c}; //первый элемент c+3, // т.е. мы идем три раза вперед на размерность с и попадаем на POINT char ***cpp = cp; //ехал указатель через указатель, // видит в реке указатель, // сунул указатель в указатель, // гитлер гитлер гитлер гитлер printf("%s", **++cpp); //выводится POINT printf("%s", *--*++cpp+3); //снова шастаем по указателям, // приходим на ENTER, прыгаем на 3 размера данного указателя вперед // (теперь это char жизнь, сынок, это просто, как ездить на велосипеде, // и мы в аду и ты горишь и велосипед горит) // вместо ENTER получаем ER (ENT ER) // выводится в итоге POINTER дальше сам понимаешь. И да, ужасы у вас какие на уроках. когда кто-нибудь посмотрит в этот ужасный пример и более подробно разберет, с радостью удалю ответ, мне главное чтобы ОП бритвой по венам не прошелся. тут намек на решение, спасибо за хороший пример, pointer stew гуглится на ура, задача из книги "The C Puzzle Book" p.s. Pointer stew переводится как (густой)суп (похлебка, тушеный) указатели. Cуп из указателей. Красиво.Ответ 2
По второй части вопроса: Также не понимаю почему код printf("%s", *(c+1)); компилится, а printf("%s", *++c); не компилится. Потому что ++c изменяет само значение c, а его менять нельзя - c - это массив (да, фактически это указатель на первый элемент массива, но таковы правила игры).Ответ 3
Выполнение префиксных инкрементов/декркментов и разыменоаний указателей происходит от названия переменной в левую сторону, причем запись А[i] равносильна *(A+i), поэтому без дополнительных круглых скобок обращение к элементу массива через квадратные скобки будет выполняться первым. И по этой же причине абсолютно валидна запись i[A], можете попробовать написать так на контрольной :D а теперь перейдем к вашему коду: printf("%s", **++cpp); указатель срр увеличивается на 1, и указывает на с+2, с+2 это элемент массива с с индексом 2 (помним, что отсчет идет с нуля) разыменовываем его двумя звездочками, и получаем строку "POINT". printf("%s", *--*++cpp+3); здесь срр снова увеличивается на 1, и начинает указывать на с+1, далее разыменовываем его 1 раз, теперь наш кусок выражения указывает на "NEW" уже в самом массиве с(массив ср содержит лишь копии указателей на разные части с), полученный с+1 декрементируем, получаем с, разыменовываем еще раз, получаем строку "ENTER", и лишь теперь выполняется прибавление к этой строке(то есть к указателю на ее нулевой элемент) тройки, то есть начало строки сдвигается на 3 и получается "ER" printf(" %s", *cpp[-2]+3); сначала выполняется обращение к срр[-2], то есть был с+1, стал с+3 и при этом произошло разыменование на один уровень, срр[-2] равносильно *(срр-2), разыменовываем еще раз, получаем строку "FIRST", сдвигаем ее начало на 3 символа и получаем "ST" printf("%s", cpp[-1][-1]+1); помним, что срр все еще равен с+1, и далее первые скобки дают нам с+2, а вторые дают нам строку "NEW", увеличиваем ее начало на 1, и получается "EW".
Комментариев нет:
Отправить комментарий