我们可以在变量名中写注释吗?

问题描述

int main()
{
     i/*nt*/a = 10;
     return 0;
}

如果我具有上面的代码并且想要计算令牌,那么它是14还是13个令牌?

在变量名中写注释是否有效?您可以假设int iint aint ia是全局定义的。

解决方法

在程序翻译的第3阶段中删除了注释 1 每个注释都被一个空格字符代替。所以注释/*nt*/绝对不是令牌。

如果intmainiareturn中的任何一个均未定义为预处理宏,则解析程序会产生 14 令牌(不是13个):

int main ( ) { i a = 10 {{ 1}} ; return 0 ;

除非}被定义为带有i语句的类型,否则会出现语法错误,因为typedef与C语法中的规则不匹配。

因此您不能在变量名内 中写注释,注释会将标识符分成2个单独的标记。对于任何预处理和C语言令牌 2 都是如此。

但是请注意,您可以在不寻常的位置插入注释,例如在一元运算符与其操作数之间或i a与预处理指令及其参数之间插入注释:

#

但是上面的宏定义并未定义类似于函数的宏,而是定义了扩展为/**/#/**/include/**/<stdio.h>/**/////////////////////// /**/#/**/define/**/STAT/**/(/**/a/**/)/**/-/**/1/**//// /**/#/**/ifdef/**/STAT/**////////////////////////////// /**/int/**/main/**/(/**/)/**/{/**////////////////////// /**/int/**/a/**/=/**/+/**/1/**/;/**//////////////////// /**/printf/**/(/**/"Hello "/**/"world!\n"/**/)/**/;/**/ /**/return/**/STAT/**/;/**///////////////////////////// /**/}/**/////////////////////////////////////////////// /**/#/**/endif/**////////////////////////////////////// 的常规宏STAT

变量名称,与其他任何令牌一样,可以用转义的换行符分隔。转义的换行符是序列或( a ) - 1,后跟换行符。在程序翻译的第2阶段,这些序列将从源代码中删除。它们的主要目的是打破多行上的长宏定义。

下面是一个代码片段 3 ,它产生相同的14个令牌:

\

注意代码着色器如何错过切片和切块的关键字和注释:)


1)此行为是在ANSI-C或C89中指定的。某些古老的编译器的行为略有不同,导致令牌粘贴,但是这种特殊性仅在历史上有意义。

2)您可以利用以下事实几乎可以在字符串常量中插入注释:相邻的字符串常量在程序翻译的第6阶段被连接:\ i\ nt\ ma\ in() {\ i/\ *nt\ */a \ = 10; r\ et\ urn\ 0;}

3)这种圣诞树表示样式并不是要在实际程序中使用,它说明了如何滥用C的输入处理功能。更多精心制作的技巧赢得了The International Obfuscated C Code Contest

,

从词法的角度来看,注释与空白相同。

C standard的第6.4p3节中关于词法元素的规定为:

...预处理令牌可以用空格分隔; 它由注释(稍后描述)或空白组成 字符(空格,水平标签,换行符,垂直标签和 换页),或两者兼有。 ...

更具体地说,评论被翻译成一个空格。这在5.1.1.2p3节中指定:

源文件被分解为预处理令牌和 空格字符序列(包括注释)。一种 源文件不得以部分预处理令牌或以 部分评论。 每个注释都替换为一个空格字符。 换行符将保留。是否每个非空序列 保留或替换换行符以外的空白字符 实现定义了一个空格字符。

为了说明这一点,如果通过预处理器传递代码,则会得到:

  int main()
  {
       i a = 10;
       return 0;

  }

因此,注释(如空格)可用于分隔令牌。

这意味着该代码将包含14个令牌,而不是13个令牌。

,

结果就像您写过一样:

i a = 10;

否:

ia = 10;
,

请参见翻译(也称为编译)Phase 3,第2步:“每个注释都替换为一个空格字符”。

因此,从概念上讲,i/*nt*/a在那时变成i a

,

只需检查代码的形式

%2

在预处理后将具有。只需在编译器中添加“ -E”标志, gcc -E myscript.c 您将得到结果:

     int main()
    {
        int i/*nt*/a = 10;
        return 0;
    }

很明显,您可以得出结论,这是一个错误。

,

是的,您可以这样做。注释将被编译器跳过。它们不会影响变量。就是一样,只是别忘了结束评论标签。