Открыть список
Как стать автором
Обновить

Правило чтения по спирали

C++
Перевод
Автор оригинала: David Anderson
Техника, известная как «Чтение по спирали/по часовой стрелке» (“Clockwise/Spiral Rule”) позволяет любому программисту разобрать любое объявление языка Си.

Следуйте этим простым шагам:

1. Начиная с неизвестного элемента, двигайтесь по спирали/по часовой стрелке; при этом заменяйте следующие элементы соответствующими фразами:
  • [X] или [] => массив размера X типа… или массив неопределённого размера типа...
  • (type1, type2) => функция, принимающая типы type1, type2 и возвращающая...
  • * => указатель на...

2. Двигайтесь по спирали/по часовой стрелке, пока не будут пройдены все элементы.
3. Всегда сначала надо разрешать выражения в скобках!

Пример 1: Простое объявление


+-------+<br>
| +-+ |<br>
| ^ | |<br>
char *str[10];<br>
^ ^ | |<br>
| +---+ |<br>
+-----------+<br>


Спросим себя, что такое str?
str — это...

Двигаемся по спирали/по часовой стрелке, начиная с str, и первый символ, который мы видим это '[', значит это массив, и так:
str — это массив размера 10 типа...

Продолжаем двигаться по спирали/по часовой стрелке, и следующее, что мы встречаем, это символ '*', значит у нас есть указатели, и так:
str — это массив размера 10 типа указатель на...

Двигаемся по спирали и видим конец строки, потому двигаемся дальше и видим тип 'char', и так:
str — это массив размера 10 типа указатель на char.

Мы посетили все элементы, т.е. всё, мы разобрали это выражение!

Пример 2: Объявление указателя на функцию


+--------------------+<br>
| +---+ |<br>
| |+-+| |<br>
| |^ || |<br>
char *(*fp)( int, float *);<br>
^ ^ ^ || |<br>
| | +--+| |<br>
| +-----+ |<br>
+------------------------+<br>

Cпросим себя, что такое fp?
fp — это...

Двигаемся по спирали/по часовой стрелке, и первое что мы видим, это ')'; таким образом fp внутри скобок и мы продолжаем спираль внутри скобок и следующий символ это '*', и так:
fp — это указатель на...

Мы теперь вне скобок и, продолжая двигаться по спирали видим '(', т.е. это функция, и так:
fp — это указатель на функцию, принимающую int и указатель на float, возвращающую...

Продолжая двигаться по спирали, встречаем символ '*', и так:
fp — это указатель на функцию, принимающую int и указатель на float, возвращающую указатель на...

Продолжая двигаться по спирали, встречаем символ ';', но так как ещё не все символы обработаны, то продолжаем и встречаем 'char', и так:
fp — это указатель на функцию, принимающую int и указатель на float, возвращающую указатель на char.


Пример 3: Ultimate


+-----------------------------+<br>
| +---+ |<br>
| +---+ |+-+| |<br>
| ^ | |^ || |<br>
void (*signal(int, void (*fp)(int)))(int);<br>
^ ^ | ^ ^ || |<br>
| +------+ | +--+| |<br>
| +--------+ |<br>
+----------------------------------+<br>

Спросим себя, что такое signal?
Обратите внимание, signal внутри скобок, так что сначала надо разобрать выражение внутри! Двигаясь по спирали/по часовой стрелке, мы видим '(', и так:
signal — функция, принимающая int и ...

Хм, мы можем использовать то же правило на символе 'fp', и так, что такое fp? fp также внутри скобок, так что мы продолжаем и видим '*', и так:
fp — это указатель на...

Двигаясь по спирали/по часовой стрелке, мы видим '(', и так:
fp — это указатель на функцию, принимающую int, возвращающую...

Двигаясь по спирали/по часовой стрелке, мы видим 'void', и так:
fp — это указатель на функцию, принимающую int, возвращающую void.

Мы закончили с fp, так что продолжим с signal, и сейчас мы имеем:
signal — функция, принимающая int и указатель на функцию, принимающую int, возвращающую void, возвращающая...

Мы всё ещё внутри скобок, так что следующий символ это '*', и так:
signal — функция, принимающая int и указатель на функцию, принимающую int, возвращающую void, возвращающая указатель на...

Мы разрешили элементы внутри скобок, продолжая по спирали получаем символ '(', и так:
signal — функция, принимающая int и указатель на функцию, принимающую int, возвращающую void, возвращающая указатель на функцию, принимающую int и возвращающую...

Наконец, мы продолжаем двигаться, и последним символом мы видим 'void', и так, наше полное описание таково:
signal — функция, принимающая int и указатель на функцию, принимающую int, возвращающую void, возвращающая указатель на функцию, принимающую int и возвращающую void.


Это правило применимо и для понимания атрибутов const и volatile. Например:
const char *chptr;

Итак, что такое chptr?
chptr — это указатель на char неизменяемый.

А как насчёт такого:
char * const chptr;

Итак, что такое chptr?
chptr — это неизменяемый указатель на char.

И наконец:
volatile char * const chptr;

Итак, что такое chptr?
chptr — это неизменяемый указатель на char volatile.
Теги:сиси плюс плюс
Хабы: C++
Всего голосов 145: ↑132 и ↓13 +119
Просмотры11.1K

Комментарии 42

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

Похожие публикации

C# Developer. Professional
30 апреля 202165 000 ₽OTUS
Рефакторинг кода на языке C#
11 мая 202130 200 ₽Luxoft Training
SEO-специалист
22 апреля 202136 000 ₽GeekBrains
Тренажер product-менеджера
22 апреля 202134 200 ₽SkillFactory

Лучшие публикации за сутки