Как вы читаете декларации C?

Я слышал о некоторых методах, но никто из них не застрял. Лично я стараюсь избегать сложных типов в C и пытаюсь разбить их на компонент typedef.

Теперь я столкнулся с сохранением некоторого унаследованного кода от так называемого «трехзвездочного программиста», и мне трудно читать некоторые из *** кода [] [].

Как вы читаете сложные декларации C?

В этой статье объясняются относительно простые 7 правил, которые позволят вам прочитать любое объявление C, если вы захотите или хотите сделать это вручную: http://www.ericgiguere.com/articles/reading-c-declarations.html

  1. Найдите идентификатор. Это ваша отправная точка. На листе бумаги напишите «объявить идентификатор как».
  2. Посмотрите направо. Если там ничего нет, или есть правильная скобка “)”, перейдите к шагу 4.
  3. Теперь вы располагаетесь либо на дескрипторе массива (левая скобка), либо на функции (левая скобка). Может быть последовательность из них, заканчивающаяся либо несогласованной правой скобкой, либо концом декларатора (точка с запятой или «=» для инициализации). Для каждого такого дескриптора, читающего слева направо:

    • если пустой массив «[]», напишите «массив»,
    • если массив с размером, напишите «размер массива»,
    • если функция «()», напишите «возврат функции»

    Остановитесь в непревзойденной скобке или в конце объявления, в зависимости от того, что наступит раньше.

  4. Вернитесь в исходное положение и посмотрите влево. Если там ничего нет, или есть левая скобка “(“, goto step 6.
  5. Теперь вы располагаетесь в дескрипторе указателя «*». Там может быть последовательность из них влево, заканчивающаяся либо непревзойденной левой скобкой “(” или начало декларатора. Чтение справа налево, для каждого указателя дескриптора пишут “указатель на”. Остановить в несогласованной скобке или начало декларатора, в зависимости от того, что наступит раньше.
  6. На данный момент у вас есть либо выражение в скобках, либо полный декларатор. Если у вас есть выражение в скобках, рассмотрите его как новую отправную точку и вернитесь к шагу 2.
  7. Запишите спецификатор типа. Стоп.

Если у вас все в порядке с инструментом, то я второй предлагаю использовать программу cdecl : http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html

Обычно я использую то, что иногда называют «правым правилом по часовой стрелке». Это происходит так:

  • Начните с идентификатора.
  • Идите прямо к нему.
  • Затем двигайтесь по часовой стрелке и идите в левую сторону.
  • Двигайтесь по часовой стрелке и идите в правую сторону.
  • Сделайте это до тех пор, пока декларация не будет полностью проанализирована.

Существует дополнительное мета-правило, о котором нужно позаботиться:

  • Если есть круглые скобки, завершите каждый уровень круглых скобок, прежде чем перемещаться.

Здесь «движение» и «перемещение» где-то означает чтение символа. Правила для этого:

  • * – указатель на
  • () – возврат функции
  • (int, int) – функция, принимающая два ints и возвращающая
  • int , char и т. д. – int , char и т. д.
  • [] – массив
  • [10] – массив из десяти
  • и т.п.

Так, например, int* (*xyz[10])(int*, char) читается как:

xyz – это

массив из десяти

указатель на

функция принимает int * и char и возвращает

int *

Одно слово: cdecl

Damnit, избитый на 15 секунд!

Cdecl (и c ++ decl) – это программа для кодирования и декодирования объявлений типа C (или C ++).

http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html

Когда я делал C, я использовал программу cdecl. Похоже, что он находится в Ubuntu Linux в пакете cutils или cdecl, и он, вероятно, доступен в другом месте.

cdecl предлагает интерфейс командной строки, поэтому давайте попробуем:

 cdecl> explain int ***c[][] declare c as array of array of pointer to pointer to pointer to int 

другой пример

  explain int (*IMP)(ID,SEL) declare IMP as pointer to function (ID, SEL) returning int 

Однако есть целая глава об этом в книге «C Deep Secrets», названной «Unscrambling declarations in C.

Приветствую Фридриха

Также есть веб-версия cdecl, которая довольно гладкая.

Общие проблемы с читабельностью include указатели на функции и тот факт, что массивы действительно являются указателями , а многомерные массивы – это одномерные массивы (которые действительно являются указателями). Надеюсь, что это помогает.

В любом случае, всякий раз, когда вы понимаете декларации, возможно, вы можете найти способ упростить их, чтобы сделать их более читаемыми для следующего парня.

Автоматизированное решение – cdecl.

В общем, вы объявляете переменную так, как вы ее используете. Например, вы разыскиваете указатель p как:

 char c = * p

вы заявляете это аналогичным образом:

 char * p;

То же самое касается волосатых указателей функций. Давайте объявим f хорошим старым «указателем на функцию, возвращающим указатель на int», и внешнюю декларацию, чтобы быть смешной. Это указатель на функцию, поэтому мы начинаем с:

 extern * f ();

Он возвращает указатель на int, поэтому где-то впереди есть

 extern int * * f ();  // XXX еще не совсем

Итак, что такое правильная ассоциативность? Я никогда не помню, поэтому используйте скобки.

 extern (int *) (* f) ();

Объявите его так, как вы его используете.

Читайте справа налево.

 ***code[][] 
  • code [] [] является многомерным массивом
  • * code [] [] является многомерным указателем массива
  • ** code [] [] является многомерным указателем массива указателю на указатель
  • *** code [] [] является многомерным указателем на указатель на указатель на указатель

Просто наткнулся на освещающий раздел в разделе « Развитие языка C »:

Для каждого объекта такого скомпонованного типа уже существовал способ упоминания базового объекта: индексировать массив, вызывать функцию, использовать оператор указателя на указателе. Аналогичные рассуждения привели к синтаксису объявления для имен, отражающих синтаксис выражения, в котором обычно появляются имена. Таким образом,

int i, *pi, **ppi;

объявить целое число, указатель на целое число, указатель на указатель на целое число. Синтаксис этих объявлений отражает наблюдение, что i, * pi и ** ppi все дают тип int при использовании в выражении. По аналогии,

int f(), *f(), (*f)();

объявить функцию, возвращающую целое число, функцию, возвращающую указатель на целое число, указатель на функцию, возвращающую целое число;

int *api[10], (*pai)[10];

объявить массив указателей на целые числа и указатель на массив целых чисел. Во всех этих случаях объявление переменной напоминает ее использование в выражении, тип которого совпадает с именем, указанным во главе объявления.

  • самореферентное определение структуры?
  • Переслать-объявить перечисление в Objective-C
  • Повторяющиеся typedefs - недопустимы в C, но действительны в C ++?
  • массив фиксированной длины typedef
  • Обеспечьте сильную проверку типов в C (строгость строгости для typedefs)
  • Что такое «форвардная декларация» и разница между «typedef struct X» и «struct X»?
  • typedef struct vs struct definitions
  • Почему «typdef struct {struct S * s; } S; ", содержащий указатель на компиляцию того же типа?
  • typedef указатель const weirdness
  • C Typedef и Struct Question
  • Если я делаю `typedef` в C или C ++, когда мне следует добавить` _t` в конце typedef'ed типа?
  • Interesting Posts

    Добавить миграцию ссылочного столбца в Rails 4

    Java List.add () UnsupportedOperationException

    Как вы теперь импортируете проект Eclipse в Android Studio?

    Как заблокировать ориентацию в портретном режиме в веб-приложении iPhone?

    Есть ли способ предоставить разрешения на чтение и запись себе для системных файлов на Mac OSX 10.11.2

    Boost Spirit: «Семантические действия – это зло»?

    Как узнать, когда был записан / сожжен звуковой диск (CD)?

    Почему ПК все еще требуют батареи CMOS?

    Использовать более поздний кадр для миниатюры видео в Windows 7

    Как я могу использовать гарнитуры iPhone в качестве компьютерного микрофона?

    Как открыть приложение «Настройки» из моего приложения?

    Что означает квадратная скобка в приведенном ниже коде?

    Как принудительно выйти из системы в django?

    Рассчитать общее количество дней за определенный месяц

    Как добавить запятые для номера каждые 3 цифры в Objective C?

    Давайте будем гением компьютера.