Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我们可以在变量名中写注释吗?_C_Lexical Analysis - Fatal编程技术网

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

C 我们可以在变量名中写注释吗?,c,lexical-analysis,C,Lexical Analysis,如果我有上面的代码,我想计算代币的数量,是14还是13 在变量名中写入注释是否有效?您可以假定inti、inta、intia是全局定义的。结果将与您编写的代码相同: int main() { i/*nt*/a = 10; return 0; } 不是: 从词汇的角度来看,注释与空白是相同的 关于词汇元素的第6.4p3节规定: 。。。预处理令牌可以用空格分隔; 这包括注释(稍后描述)或空白 字符(空格、水平制表符、新行、垂直制表符和 表单提要),或两者都有 更具体地说,注释被

如果我有上面的代码,我想计算代币的数量,是14还是13


在变量名中写入注释是否有效?您可以假定
inti
inta
intia
是全局定义的。

结果将与您编写的代码相同:

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


从词汇的角度来看,注释与空白是相同的

关于词汇元素的第6.4p3节规定:

。。。预处理令牌可以用空格分隔; 这包括注释(稍后描述)或空白 字符(空格、水平制表符、新行、垂直制表符和 表单提要),或两者都有

更具体地说,注释被翻译成单个空间。这在第5.1.1.2p3节中有规定:

将源文件分解为预处理标记和 空格字符序列(包括注释)。A. 源文件不应以部分预处理令牌或 部分评论每条注释都用一个空格字符替换。 保留新行字符。每个非空序列 保留或替换除新行以外的所有空白字符 实现定义了一个空格字符

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

ia = 10;
因此,注释和空白一样,用于分隔标记

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

参见翻译(又称编译),第2步:“每个注释替换为一个空格字符”


因此,从概念上讲,
i/*nt*/a
在该点变为
ia

在程序翻译的第3阶段删除注释1:每个注释由一个空格字符替换。因此注释
/*nt*/
绝对不是一个标记

如果
int
main
i
a
return
均未定义为预处理宏,则解析程序会生成14个标记(不是13个):

int
main
i
a
<10
返回
<0

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

因此,不能在变量名中写入注释,注释会将标识符拆分为两个单独的标记。这适用于任何预处理和C语言标记2

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

/**/#/**/包括/**//**///////////////////////
/**/#/**/定义/**/STAT/**/(/**/a/**/)/**/-/**/1/**////
/**/#/**/ifdef/**/STAT/**//////////////////////////////
/**/int/**/main/**/(/**/)/**/{/**//////////////////////
/**/int/**/a/**/=/**/++/**/1/**//**////////////////////
/**/printf/**/(/**/“你好”/**/“世界!\n”/**/)/**//**/
/**/返回/**/STAT/**//**/////////////////////////////
/**/}/**///////////////////////////////////////////////
/**/#/**/恩迪夫/**//////////////////////////////////////
但是上面的宏定义并没有定义类似宏的函数,而是一个扩展到
(a)-1
的常规宏
STAT

变量名和任何其他标记一样,可以通过转义换行来拆分。转义换行符是紧跟着换行符的序列或
\
。这些序列在程序翻译的第二阶段从源代码中删除。它们的主要目的是在多行上打断长宏定义

下面是生成相同14个令牌的代码片段3:

\
我\
新界\
妈\
在()
{\
我/\
*新界\
*/a\
= 10;
r\
et\
瓮\
0;}
请注意,代码着色程序是如何漏掉分片和分片的关键字和注释的:)


1) 此行为在ANSI-C aka C89中指定。一些古代的编撰者有着微妙的不同行为,导致了标记粘贴,但这种特殊性仅具有历史意义

2) 您几乎可以利用相邻字符串常量在程序翻译的第6阶段连接的事实在字符串常量中插入注释:
printf(“Hello”/*我的名字是Luca*/“world!\n”)


3) 这种圣诞树表示风格并不适用于实际程序,它说明了如何滥用C的输入处理功能。更多精心设计的技巧获胜了

只需检查您的代码是什么形式

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

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

     int main()
    {
        int i/*nt*/a = 10;
        return 0;
    }
e。sharaborin@landau:~$gcc-E myscript.c
#1“myscript.c”
# 1 ""
# 1 ""
# 31 ""
#1“/usr/include/stdc predef.h”1 3 4
# 32 "" 2
#1“myscript.c”
int main()
{
int i a=10;
返回0;
}

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

在ANSI之前的“传统”C中,至少在由实现时,它会扩展到
ia=10。这是一个多么有趣的问题-为什么我以前从来没有想到过?@javadba:因为明智的人不会想到做这样的事情?如果你真的想做,你可以改用Fortran。字符串外的空白在第一个解析阶段被删除。我正要编辑标题“…在变量名内…”,但后来意识到您可能实际上指的是“之间”。(我想编辑它,因为原始标题的答案是“为什么,显然!”重要的部分是“没有空格”。)标题“注释(没有周围的空格)是否在C中分隔标记?”是否表达了您的实际问题?注释不用于扩展讨论;这段对话已经结束。
     int main()
    {
        int i/*nt*/a = 10;
        return 0;
    }
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;
}