C编译器如何解析以下C语句?

Yog*_*tal 11 c compiler-construction printf lexical-analysis

请考虑以下几行:

int i;
printf("%d",i);
Run Code Online (Sandbox Code Playgroud)

词法分析器会进入字符串解析%d作为单独的标记,还是将"%d"解析为一个标记?

Kru*_*lur 25

这里有两个解析器:首先是C编译器,它将解析C文件并基本上忽略字符串的内容(尽管现代C编译器也会解析字符串以帮助捕获错误的格式字符串 - %转换之间不匹配说明符和传递printf()给要转换的相应参数).

下一个解析器是内置于C运行时库中的字符串格式解析器.这将在运行时调用,以在您调用时解析格式字符串printf.这个解析器当然非常简单.

我没有检查过,但我猜想有助于检查错误格式字符串的C编译器将实现类似printf的解析器作为后处理步骤(即使用自己的词法分析器).


sep*_*p2k 19

字符串文字是单个标记.上面的代码将被标记为这样:

int     keyword "int"
i       identifier
;       semicolon
printf  identifier
(       open paren
"%d"    string literal
,       comma
i       identifier
)       closing paren
;       semicolon
Run Code Online (Sandbox Code Playgroud)

  • 我认为OP希望更多地了解"%d"将生成长度为1或2的char数组(即"\n"将生成长度为1的char数组) - 我认为他正在寻找的答案是它将是一个字符串文字,其中包含两个不同的字符(然后通过*printf方法在运行时进一步解析). (5认同)

Sha*_*our 7

"%d"是一个字符串文字,它将被C预处理器和编译器看作一个标记,我们可以通过草拟C99标准部分6.4 Lexical元素来定义以下标记:

token:
  keyword
  identifier
  constant
  string-literal
  punctuator
Run Code Online (Sandbox Code Playgroud)

和以下预处理令牌:

preprocessing-token:
  header-name
  identifier
  pp-number
  character-constant
  string-literal
  punctuator
  each non-white-space character that cannot be one of the above
Run Code Online (Sandbox Code Playgroud)

并说:

令牌是最小词法元件在翻译的语言的 阶段7个8的令牌的种类是:关键字,标识符,常量,字符串文字,和标点符号.预处理标记是翻译阶段3到6中语言的最小词汇元素.预处理标记的类别是:标题名称,标识符,预处理数字,字符常量,字符串文字,标点符号和单个非空白字符不要与其他预处理令牌类别词汇匹配.58)[...]

翻译的不同阶段将在5.1.1.2 翻译阶段进行介绍,我将在此重点介绍一些相关的翻译阶段:

[...]

3源文件被分解为预处理标记 6)和空白字符序列(包括注释).

[...]

6连接相邻的字符串文字标记.

7分隔标记的空白字符不再重要.每个预处理令牌都转换为令牌.由此产生的标记在语法和语义上进行分析并翻译为翻译单元.

[...]

预处理器令牌令牌之间的区别似乎无关紧要但我们可以看到,至少在一种情况下,例如在相邻的字符串文字中,例如,"%d" "\n"您将有两个预处理器令牌,而在相位之后6,将只有一个令牌.