2014-08-30 4 views
11

Рассмотрим следующие строки:Как компилятор C анализирует следующий оператор C?

int i; 
printf("%d",i); 

Будет лексический анализатор идти в строку для разбора % и d как отдельные лексемы, или он будет разобрать «% D», как один знак?

+6

лексический анализатор будет определять '«% d»', как конкурировать строки. Следующие этапы «синтаксиса» и «семантики» компилятора идентифицируют отсутствующий аргумент и проверку типа. Если вы скомпилируете код (без 'i' в printf), вы получите предупреждение' 'format '% d' ожидает соответствующий аргумент 'int'' из-за синтаксических и семантических проверок. –

+0

Как синтаксический анализ может найти ошибку, если строка не раздельно разбирается как токен? –

+0

«синтаксический анализ» - следующий этап после слова «лексический». Компилятор кулака генерирует поток токенов (как указано в ответе sepp2k), затем поток токов далее анализируется (с использованием грамматики) и семантически проверяется на следующей фазе. –

ответ

25

Есть два парсеров на работе здесь: первый, компилятор Си, который будет анализировать файл C и в основном игнорирует содержимое строки (хотя современные компиляторы будут проанализируйте строку, чтобы помочь поймать неверные строки формата - несоответствия между спецификатором преобразования % и соответствующим аргументом, переданным в printf() для преобразования).

Следующий синтаксический анализатор представляет собой синтаксический анализатор строк, встроенный в библиотеку времени выполнения C. Это будет вызываться во время выполнения, чтобы проанализировать строку формата, когда вы вызываете printf. Этот парсер, конечно, очень прост в сравнении.

Я не проверял, но я бы предположил, что компиляторы C, которые помогают проверять строки с плохим форматированием, будут реализовывать парсер printf в качестве этапа последующей обработки (т. Е. Используя собственный лексер).

19

Строковый литерал - это единственный токен. Приведенный выше код будет лексемы, как это:

int  keyword "int" 
i  identifier 
;  semicolon 
printf identifier 
(  open paren 
"%d" string literal 
,  comma 
i  identifier 
)  closing paren 
;  semicolon 
+5

Я думаю, что OP хотел узнать больше по строкам воли «% d» сгенерирует массив символов длиной 1 или 2 (т. Е. «\ N» будет генерировать массив символов длиной 1) - I думаю, что ответ, который он ищет, заключается в том, что это будет строковый литерал с двумя разными символами в нем (который затем затем анализируется во время выполнения методом * printf). – BrainSlugs83

7

"%d" является строковый литерал и будет видно, как один знак обеими C preprocessor, а также составителем, мы можем увидеть, перейдя в draft C99 standard секции 6.4лексем который определяет следующие символы:

token: 
    keyword 
    identifier 
    constant 
    string-literal 
    punctuator 

и следующий proprocessing жетоны:

preprocessing-token: 
    header-name 
    identifier 
    pp-number 
    character-constant 
    string-literal 
    punctuator 
    each non-white-space character that cannot be one of the above 

d говорит:

маркер является минимальным элементом лексической языка в переводе фазы 7 и 8. Категории маркеров являются: ключевые слова, идентификаторы, константы, строковых литералов и знаки пунктуации. Лексема предварительной обработки минимальный лексический элемент языка в переводе фаза 3 до 6. Категории предобработки лексем являются: имена заголовков, идентификаторов, предобработка числа, символьные константы, строковых литералы , знаки пунктуация, и одиночные, не пробельные символы, которые делают не лексический соответствуют другому Preprocessing токенов categories.58) [...]

различных этапов перевода охватываемых в разделе 5.1.1.2фазы перевода и я остановлюсь на некоторых из них:

[...]

3 Исходный файл разложен на предобработки лексемы 6) и последовательности пробельных символов (включая комментарии).

[...]

6 соседней строка лексема, сцепляются.

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

[...]

Различие между препроцессор лексем и лексем может показаться неуместным, но мы можем видеть, что, по крайней мере в одном случае, например, в соседних строковых литералов, например "%d" "\n" у вас было бы два токена процессора , а после фазы 6 был бы только один token.

0

Нужна библиотека функций #include «stdio.h» в верхней части ур код ...