Техника, известная как «Чтение по спирали/по часовой стрелке»
(“Clockwise/Spiral Rule”) позволяет любому программисту разобрать любое
объявление языка Си. Взято на Хабре http://habrahabr.ru/blogs/cpp/100104/.
Следуйте этим простым шагам:
1. Начиная с неизвестного элемента, двигайтесь по спирали/по часовой
стрелке; при этом заменяйте следующие элементы соответствующими фразами:
- [X] или [] => массив размера X типа… или массив неопределённого размера типа...
- (type1, type2) => функция, принимающая типы type1, type2 и возвращающая...
- * => указатель на...
2. Двигайтесь по спирали/по часовой стрелке, пока не будут пройдены все элементы.
3. Всегда сначала надо разрешать выражения в скобках!
Пример 1: Простое объявление
+-------+
| +-+ |
| ^ | |
char *str[10];
^ ^ | |
| +---+ |
+-----------+
Спросим себя, что такое str?
str — это...
Двигаемся по спирали/по часовой стрелке, начиная с str, и первый символ, который мы видим это '[', значит это массив, и так:
str — это массив размера 10 типа...
Продолжаем двигаться по спирали/по часовой стрелке, и следующее, что мы
встречаем, это символ '*', значит у нас есть указатели, и так:
str — это массив размера 10 типа указатель на...
Двигаемся по спирали и видим конец строки, потому двигаемся дальше и видим тип 'char', и так:
str — это массив размера 10 типа указатель на char.
Мы посетили все элементы, т.е. всё, мы разобрали это выражение!
Пример 2: Объявление указателя на функцию
+--------------------+
| +---+ |
| |+-+| |
| |^ || |
char *(*fp)( int, float *);
^ ^ ^ || |
| | +--+| |
| +-----+ |
+------------------------+
Cпросим себя, что такое fp?
fp — это...
Двигаемся по спирали/по часовой стрелке, и первое что мы видим, это ')';
таким образом fp внутри скобок и мы продолжаем спираль внутри скобок и
следующий символ это '*', и так:
fp — это указатель на...
Мы теперь вне скобок и, продолжая двигаться по спирали видим '(', т.е. это функция, и так:
fp — это указатель на функцию, принимающую int и указатель на float, возвращающую...
Продолжая двигаться по спирали, встречаем символ '*', и так:
fp — это указатель на функцию, принимающую int и указатель на float, возвращающую указатель на...
Продолжая двигаться по спирали, встречаем символ ';', но так как ещё не
все символы обработаны, то продолжаем и встречаем 'char', и так:
fp — это указатель на функцию, принимающую int и указатель на float, возвращающую указатель на char.
Пример 3: Ultimate
+-----------------------------+
| +---+ |
| +---+ |+-+| |
| ^ | |^ || |
void (*signal(int, void (*fp)(int)))(int);
^ ^ | ^ ^ || |
| +------+ | +--+| |
| +--------+ |
+----------------------------------+
Спросим себя, что такое 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.
|
Комментарии
2010-11-1916:18:22 ВОТ ЭТО ДА!!