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

Can we write comments within variable names?

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

如果我有上面的代码,我想计算令牌数,是14个还是13个令牌?

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

结果就像你写的一样:

i a = 10;

不是:

ia = 10;

从词法上看,一条注释和white是一样的space。

关于词汇元素的 C standard 第 6.4p3 节指出:

... Preprocessing tokens can be separated by white space; this consists of comments (described later), or white-space characters (space, horizontal tab, new-line,vertical tab, and form-feed), or both. ...

更具体地说,一条评论被翻译成一条 space。这在第 5.1.1.2p3 节中指定:

The source file is decomposed into preprocessing tokens and sequences of white-space characters (including comments). A source file shall not end in a partial preprocessing token or in a partial comment. Each comment is replaced by one space character. New-line characters are retained. Whether each nonempty sequence of white-space characters other than new-line is retained or replaced by one space character is implementation-defined.

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

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

  }

因此评论,如白色space,用于分隔标记。

这意味着代码将包含 14 个标记,而不是 13 个。

参见翻译(a.k.a. 编译)Phase 3,第 2 步:“每条评论由一个 space 个字符替换”

所以,从概念上讲,i/*nt*/a 在那个时候变成了 i a

注释在程序翻译的第 3 阶段被删除1每个注释被一个 space 字符替换。所以评论 /*nt*/ 绝对不是令牌。

如果int、none、mainiareturn定义为预处理宏,解析程序产生 14 个令牌(不是 13 个):

intmain(){ia=10 ; return 0 ; }

除非 i 定义为带有 typedef 语句的类型,否则存在语法错误,因为 i a 不匹配 C 语法中的规则。

所以你不能在变量名里写注释,注释把标识符分成2个单独的标记。对于任何预处理和 C 语言标记都是如此 2.

但是请注意,您可以在不寻常的地方插入注释,例如在一元运算符和它们的操作数之间或在 # 和预处理指令及其参数之间:

/**/#/**/include/**/<stdio.h>/**///////////////////////
/**/#/**/define/**/STAT/**/(/**/a/**/)/**/-/**/1/**////
/**/#/**/ifdef/**/STAT/**//////////////////////////////
/**/int/**/main/**/(/**/)/**/{/**//////////////////////
/**/int/**/a/**/=/**/+/**/1/**/;/**////////////////////
/**/printf/**/(/**/"Hello "/**/"world!\n"/**/)/**/;/**/
/**/return/**/STAT/**/;/**/////////////////////////////
/**/}/**///////////////////////////////////////////////
/**/#/**/endif/**//////////////////////////////////////

但是上面的宏定义并没有定义一个function-like宏而是一个扩展为( a ) - 1.

的常规宏STAT

变量名,就像任何其他标记一样,可以用转义的换行符分隔。转义换行符是序列或 \ 紧跟换行符。这些序列在程序翻译的第 2 阶段从源代码中删除。它们的主要目的是打破多行的长宏定义。

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

\
i\
nt\
 ma\
in()
{\
i/\
*nt\
*/a \
= 10;
r\
et\
urn\
 0;}

注意代码着色器是如何遗漏切片和切块的关键字和评论的:)


1) 此行为在 ANSI-C aka C89 中指定。一些古老的编译器在导致标记粘贴时有微妙的不同行为,但这些特性仅具有历史意义。

2) 利用程序翻译阶段 6 中相邻字符串常量连接这一事实,您几乎可以在字符串常量中插入注释:printf("Hello "/* my name is Luca */"world!\n");

3) 这种 圣诞树 表示风格并不意味着要在实际程序中使用,它说明了如何滥用 C 的输入处理能力。更精巧的花样赢了The International Obfuscated C Code Contest

看看你的代码是什么形式

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

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

e.sharaborin@landau:~$ gcc -E myscript.c
# 1 "myscript.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "myscript.c"
int main()
{
    int i a = 10;
    return 0;
}

很明显,你可以断定这里有错误。