2014-08-30 51 views
11

考虑下面几行:C编译器如何解析下面的C语句?

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

将词法分析器进入串解析%d作为单独的令牌,还是会解析“%d”作为一个标志?

+6

词法分析器会将''%d“'标识为竞争串。编译器“语法”和“语义”的下一个阶段是那些标识缺少参数和类型检查的阶段。如果你编译代码(在printf中没有'i'),你将会得到''格式由于语法和语义检查'%d'''需要匹配'int'参数。 – 2014-08-30 12:59:03

+0

如果字符串没有单独解析为标记,语法分析如何发现错误? – 2014-08-30 12:59:29

+0

“语法分析”是“词法”之后的下一阶段。编译器的头部生成令牌流(如sepp2k的答案中给出的),然后进一步解析toke流(使用语法)并在下一阶段进行语义检查。 – 2014-08-30 13:01:43

回答

25

有两个分析器在这里工作:第一,C编译器,这将解析C文件,基本上忽略字符串的内容(虽然现代的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 2014-08-31 09:54:58

7

"%d"字符串文字,它将被视为由两个C preprocessor一个令牌,并且还由编译器,我们可以通过将draft C99 standard6.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预处理标记的类别为:标题名称, 标识符,预处理数字,字符常量,串 文字,标点符号,以及单个非空白字符做 不词法匹配其他预处理标记categories.58)[...]

翻译的不同阶段将在第5.1.1.2平移阶段我会在这里强调一些相关的:

[...]

3源文件是分解为预处理令牌 6)和 空白字符序列(包括注释)。

[...]

6将相邻的字符串文字标记连接在一起。

7分隔标记的空白字符不再显着。 将每个 预处理令牌转换为令牌。结果令牌是 在句法和语义上分析并翻译为翻译单元。

[...]

预处理器令牌令牌之间的区别可能看起来不相关,但我们可以看到,在至少一种情况下,例如在相邻的字符串文字例如"%d" "\n"你将有两个预处理器令牌,而在阶段6之后将只有一个令牌

0

需要一个库函数#include'stdio.h'在ur代码的顶端...