Есть ли ограничение на длину содержимого макроса? - PullRequest
0 голосов
/ 30 декабря 2018

Для встроенных программ я часто конвертирую таблицы данных в заголовок #defines, который в программе .c добавляется в переменные / массивы.

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

Пример заголовка:

#define BIG_IMAGE_BLOCK      \
    0x00, 0x01, 0x02, 0x03,  \
    0x04, 0x05, 0x06, 0x07,  \
    /* this goes on ... */   \
    0xa8, 0xa9, 0xaa, 0xab

Пример кода (avr-gcc):

const uint8_t ImageData[] PROGMEM = {
    BIG_IMAGE_BLOCK
};

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

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

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

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

- 127 уровней вложенности блоков

- 63 уровня вложенности условного включения

- 12 указателей, массиви деклараторы функций (в любых комбинациях), изменяющие арифметический, структурный, объединенный или недействительный тип в объявлении

- 63 уровня вложенности объединенных в скобки деклараторов в полном деклараторе

- 63 уровня вложенностивыражений в скобках внутри полного выражения

- 63 значимых начальных символа во внутреннем идентификаторе или имени макроса (каждое универсальное имя или расширенный исходный символ считается одним символом)

- 31 значащийначальные символы во внешнем идентификатореfier (каждое имя универсального символа, указывающее короткий идентификатор 0000FFFF или менее, считается 6 символами, каждое имя универсального символа, указывающее короткий идентификатор 00010000 или более, считается 10 символами, и каждый расширенный исходный символ считается тем же числом символов, что исоответствующее имя универсального символа, если оно есть)

- 4095 внешних идентификаторов в одной единице перевода

- 511 идентификаторов с областью блока, объявленной в одном блоке

- одновременно определены 4095 макро идентификаторовв одной единице преобразования предварительной обработки

- 127 параметров в одном определении функции

- 127 аргументов в одном вызове функции

- 127 параметров в одном макроопределении

- 127 аргументов в одном вызове макроса

- 4095 символов в строке логического источника

- 4095 символов в строковом литерале (после конкатенации)

- 65535 байт в объекте (втолько для размещенной среды)

- 15 уровней вложенности для # включенных файлов

- 1023 метки регистра для оператора переключения (исключая метки для любых вложенных инструкций переключения)

- 1023члены в одной структуре или объединении

- 1023 константы перечисления в одном перечислении

- 63 уровня вложенных определений структуры или объединения в одном списке struct-объявление

Соответствие количества символов в строке логического источника происходит потому, что раскрытие макроса будет происходить в одной строке логического источника.Например, если \ используется в определении макроса для указания многострочного макроса, все части объединяются в одну строку источника.Это требуется в разделе 5.1.1.2, пункт 1, второй пункт.

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

Практически, все реализации (компиляторы и их препроцессоры) выходят за эти пределы.Например, допустимая длина строки логического источника для компилятора gnu определяется доступной памятью.

0 голосов
/ 30 декабря 2018

Стандарт C очень слаб в определении таких ограничений.Реализация AC должна иметь возможность переводить «хотя бы одну программу» с 4095 символами в строке логического источника (C 2018 5.2.4.1).Тем не менее, он может потерпеть неудачу в других ситуациях с более короткими линиями.Длина текста замены макроса (измеряется либо в символах, либо в токенах препроцессора) явно не указывается.

Таким образом, реализации C могут иметь ограничения на длину текста замены макроса и другого текста, но это не контролируетсястандарт C и часто недостаточно хорошо документирован или вообще документирован реализациями C.

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

...