扩展分析C语言单双引号、反斜杠与注释

注释

C语言风格的注释: /* 这是注释 */
C++风格的注释: //这是注释


奇怪的注释

int main()
{
int /* */ i;                    //1.正确
char *s = "abcdefgh //hijklmn"; //2.正确://是字符串的一部分
//Is it a\
valid comment?                  //3.正确  注释可以通过续行符续行
in/* */t j;                     //4.报错
system("pause");
return 0;
}

gcc4.8.5的语法检查:


为什么4是错的? 看预编译后的结果:
执行预编译命令:gcc -E test.c -o test.i

(发现预处理阶段gcc并没有报错,说明问题是出在编译后的)


可以发现 第9行 int中间多了空格,说明注释在预编译可能会被转化成空格.

而第5行的int i中间只有一个空格,说明注释是直接被删除或合并成一个空格.

结论:注释在预编译后会替换成空格,具体替换方式由编译器决定


C风格的注释无法嵌套

预编译:

可以发现预编译后上面两个\*没有了,下面还有一个*\.

原因: C语言把遇到的第一个/*之后的数据都当作注释,直到遇到第一个/*,因此嵌套在中间的/*不会再被检查出来.且在预处理阶段会删除掉这些注释.所以嵌套的注释会留下一个*.
C风格注释采用的是就近原则.如果要能嵌套,就得使用就远原则才足以容纳多个嵌套
至于为什么不选择像代码块这样的匹配规则,可能就是历史遗留问题了,有知道的朋友可以分享在评论区.


一些特殊的注释

  • 宏中间的注释

  • 除号和*号同时使用

解决方法:

1.在/和*后加上一个空格 int b = 20/ *p

2.用圆括号把(*)括起来int b = 20/(*p) ,推荐这种方式,更为直观

注释的规则建议

  1. 注释应当准确、易懂,防止有二义性。错误的注释不但无益反而有害。

  2. 边写代码边注释,修改代码的同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要即使删除。

  3. 注释是对代码的的“提示”,而不是文档。程序中的注释应当简单明了,注释太多了会让人眼花缭乱。

  4. 对于全局数据(全局变量、常量定义等)必须要加注释。

  5. 注释的位置应与被描述的代码相邻,可以与语句在同一行,也可以在上行,但不可以放在下方。同一结构中不同域的注释要对齐。

  6. 当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读。

  7. 注释代码段时应注重“为何做(why) ",而不是怎么做”(how)“
    说明怎么做的注释一般停留在编程语言的层次,而不是为了说明问题。尽力阐述“怎么做”的注释一般没有告诉我们操作的意图,而指明“怎么做”的注释通常是冗余的。

  8. 数值的单位一定要注释。如时、分、秒等单位。

  9. 对变量的范围给出注释,尤其是参数。

  10. 对一系列的数字编号给出注释,尤其在编写底层驱动程序的时候(比如引脚编号)。

  11. 在复杂的函数中,在分支语句、循环语句结束之后需要适当的注释,方便区分各分支或循环体。(很多时候代码写长后,一个屏幕内看不到下面的代码,不知道哪个才是相应代码块匹配的花括号)


反斜杠'\'


反斜杠有续行的作用,但要注意续行后不能添加空格

如图,在续行符前加多个空格没有影响:

但续行符后不能加空格


回车也能起到换行的作用,那续行符的意义在哪?

续航符本身就有自描述性.这是续行符最大的意义,就是要明确告诉别人这里是换行的,没有二义性.如果使用回车,别人在阅读的时候有可能需要思考是不是故意换行的或者是不是不小心误敲了.


反斜杠的转义功能

转义,即对某些字符进行反斜杠,可以使之拥有超过本身的功能,

转义有两种,一种是诸如\n,\t这样的转义字符,转义后具有本身字面值之外的特殊功能;另一种诸如\",\\这种,本身字面值没有意义,而是其他功能,转义后具有字面值的意义.

转义的功能简单描述就是 (a. 字面转特殊 b. 特殊转字面)


单引号和双引号

基本概念:单引号内的是字符,双引号的是字符串


字面值,字符串,字符,字符变量的大小

sizeof分别计算大小:


为什么sizeof('1')的大小是4 ?

C99标准的规定,'a'这种单引号引起来的字符叫做整型字符常量(integer character constant),会被编译器看成整型.因此大小是4个字节

(注意:在C++中字符常量大小为1,不同平台/语言解释是不一样的.)

char类型一直在发生截断.

char类型基本上都是接收整型字符常量,而char类型只占一个字节大小,因此只能保留整型的一个字节(首字节),即截断.


不允许定义空字符常量

单引号内至少要有一个字面值


单引号内一般是一个字符,还可以有多个字符

如下图,可以发现是没有警告的.

打印结果:

但是最多4个字符,多了会告警

为什么能这样用呢? 也是上文所说的,字符常量被C语言当作整型来看待,分配了4个字节.

一个字符字面值就占一个字节,4个字符就刚好占了4个字节,整型分配的空间能够满足.

而char类型又是截断了整型的低地址字节位,因此只会输出最后一个字符字面值(小端).