文章目录
注释符号
基本注意事项
注释符号分为两种:
- C风格是
/*内容*/
- C++风格是
//内容
看上面的四种情况,只有第四种是错误的。
注释掉的内容将会在预处理阶段替换成空格。
所以第四种情况就变为了in t j;
,而把关键字int
分开是编译器不支持的,所以会报错。
还可以看到第二种情况,注释符号在字符串中是无效的。
# 和 define之间可以带空格吗?
答案是可以的。
C风格是无法嵌套的
可以看到在140行出错了,这是因为编译器只会寻找第一个/*
和第一个*/
,所以C风格的注释是无法嵌套的。
y = x/*p
当除以指针时,极易出现这样的错误,解决方法有两种
强烈推荐第二种加括号的方式。
注释的基本要求
-
注释应当准确、易懂,防止有二义性。错误的注释不但无益反而有害。
-
边写代码边注释,修改代码的同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要及时删除。
-
注释是对代码的“提示”,而不是文档。程序中的注释应当简单明了,注释太多了会让人眼花缭乱。
-
一目了然的语句不加注释。
例如:
i++; //i加1
,i加1完全就是多余的注释。 -
对于全局数据(全局变量、常量定义等)必须要加注释。
-
注释采用英文,尽量避免在注释中使用缩写,特别是不常用的缩写。
有的编译器不能显示中文,所以当有中文出现的代码用该编译器打开时将会是一团乱码(这种编译器如今很少见了)。
对于英文差的人来说,还是用中文,否则用英文写出错的注释还不如不写。
-
注释的位置应与被描述的代码相邻,可以与语句在同一行,也可以在上行,但不可以放在下方。同一结构中不同域的注释要对齐。
-
当代码比较长,特别是有多重嵌套时,应当在一些段落的结束处加注释,便于阅读。
-
注释的缩进要与代码的缩进一致。
-
注释代码段时应注重“为何做(why)”,而不是“怎么做(how)”。
说明怎么做的注释一般停留在编程语言的层次,而不是为了说明问题。尽力阐述“怎么做”的注释一般没有告诉我们操作的意图,而指明“怎么做”的注释通常是冗余的。
-
数值的单位一定要注释。
注释应该说明某数值的单位到底是什么意思,比如:关于长度的必须说明单位是毫米、米、还是千米等。
-
对变量的范围给出注释,尤其是参数。
-
对一系列的数字编号给出注释,尤其在编写底层驱动程序的时候(比如引脚编号)。
-
对于函数的入口/出口数据、条件语句、分支语句给出注释。
条件和分支语句往往是程序实现某一特定功能的关键。对于维护人员来说,良好的注释能帮助更好地理解程序,有时甚至优于看设计文档。
-
避免在一行代码或表达式的中间插入注释。
除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。
-
复杂的函数中,在分支语句、循环语句结束之后需要适当的注释,方便区分各分支或循环体。
-
对于不需要被编译的区域要使用条件编译来实现。(不推荐)
另外还有一种基于if判断,代码运行期间处理。严重不推荐
接续符与转义符
续行功能
C语言里以反斜杠\
标识断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符自动接续到前一行。但是注意:反斜杠之后不能有空格。接下来测试一下:
注意一点:在VS2022中,有时即使不加\
,换行也是有效的。但是这样的编码风格非常不推荐,当出现这样的代码时,是无法清晰的告诉用户该代码究竟是接续呢还是书写错误。所以,当我们需要进行接续时,一定要使用接续符\
。
接续符后加空格是不正确的,而不加接续符的效果跟加了接续符的效果确实一模一样的,但是不加接续符的编码风格及其不推荐!
转义
反斜杠除了可以被用作接续符外,还能被用作转义字符的开始标识。
C中,有一些字符,就是它的字面意思,比如a 、b、c
。也有一些字符,本事就是特殊含义的,比如“、'、\
。
转义的本质含义是:字面转特殊,或者特殊转字面。
单引号和双引号
基本理解
我们知道双引号引起来的都是字符串常量,单引号引起来的都是字符常量。更加准确的来说,单引号引起来的都是整型字符常量,为什么这样说呢,看下面例子。
对于字符串的大小,想必我们是很清晰的,字符串的末尾有个隐藏的\0
,所以算大小的时候其实算了两个字符1
和\0
,大小是2。那么为什么字符的大小不是1而是4呢?
其实,编译器在给字符分配内存的时候,分配的大小就是4个字节,字符的大小本来就是4个字节。所以我们常说字符其实是整型。
但是字符变量的并不是4而是1,因为char
类型的内存大小就是1,没错,我们在将字符常量赋值给字符变量的过程中,其实都在进行截取,截取整型的四个字节的低字节处,然后赋值给字符变量。看接下来的例子。
由于截取时,是从低字节处开始截取,而char
类型变量只能截取一个字节,所以只会截取字符常量的低字节的那个字符,也就会出现上图的现象。
而由于字符常量其实是四个字节,也就是说,一个字符常量里只能有四个字符。
空字符与空字符串
空字符,即字符常量是一个空,这本身就是毫无意义的,所以编译器报错。
空字符串,但其实里面有一个隐藏的\0
,所以空字符有意义,并且大小是1。
为何计算机需要字符
计算机本质只认识二进制,那么计算机为何需要字符呢?直接全部二进制不香吗?
因为计算机是为了解决人的问题,可是,人怎么知道计算机解决了人的问题?当计算机输出二进制结果时,一般人是不能够直接看懂的。
所以,为何计算机需要字符呢?本质是为了让人能看懂。
那为什么又是英文的呢?中文不香吗?
最早的计算机是美国人发明的,他们的语言是英语,仅是由26个英文字母和一堆标点符号组成的,并且计算机刚开始发明,美国人只需要解决美国人的问题就可以,所以就有了现在的简单字符。
而由于计算机只认识二进制,而人只认识字符。所以,一定要有一套规则,用来进行二进制和字符的转化,这个就叫做ASCII码表。
逻辑运算符
&&
级联两个(多个)逻辑表达式,必须同时为真,结果才为真。与&
(按位与)是完全不同的概念。
||
级联两个(多个)逻辑表达式,必须至少一个为真,结果才为真。与|
(按位或)是完全不同的概念。
短路
&&
的操作数(语句),只要有一个为假,其它的操作数(语句)便不再执行。
||
的操作数(语句),只要有一个为真,其它的操作数(语句)便不再执行。
这就是短路。
利用短路的特性,可以实现以上的类似于if
的功能。
位运算符
基本概念
&
是两个数的二进制的相对应的比特位都为1时,结果为1;反之,结果为0。
|
是两个数的二进制的相对应的比特位至少有一个为1时,结果为1;反之,结果为0。
^
是两个数的二进制的相对应的比特位相异时,结果为1;相同时,结果为0。
~
是将该数的二进制位全部取反。
&& 、|| VS &、 |
&&,||
级联的是多个逻辑表达式,需要的是真假结果。
&,|
级联的是多个数据,逐比特位进行位运算。
逻辑结果:吃了吗?
数据结构:吃了多少?
关于^
对^的三种理解
- 逐比特位,相同为假,相异为真
- 任何数和0异或,都是它本身
- 支持结合律和交换律
第一种理解上图已展示,接下来看后两种理解
先看前三行,任何数字和0异或都是它本身,其实很好理解,因为0的32个比特位都是0,而3的比特位中是0的异或后相同,结果仍为0,而3的比特位中是1的异或后相异,结果为1,其实总的结果还是3本身。所以可以得出该结论。
再看后三行,先是3和3异或,两个相同的数,比特位也都对应相同,结果为0,而0和4异或,结果就还是4了。看最后两行,看到结果仍是4,也验证了异或操作符满足交换律和结合律。
交换两个整数
这里有三种交换两数的方法,第一种是最常见的:
接下来是第二种:
但是这种方法是很有可能出错误的,因为两个相同类型的变量相加时,得出的结果有可能会超出该类型的最大值,导致得出的结果是截取之后的结果,而此时就会出错。
最后是方法三:
该方法揉合了对^的三种理解,并且是不会出现任何错误的一种方法。
位操作符需要用宏定义好后再使用。
指定比特位置为1
指定比特位置为0
【规则2-19】其实是一个整型提升问题
无论任何位运算符,目标都是要计算机进行计算的,而计算机中只有CPU具有运算能力(可以这样简单理解),但计算的数据,都在内存中。故,计算之前(无论任何运算),都必须将数据从内存拿到CPU中,拿到CPU哪里呢?毫无疑问,在CPU的寄存器中。
而寄存器本身,随着计算机位数的不同,寄存器的位数也不同。一般,在32位下,寄存器的位数是32位。
可是char类型数据只有8个比特位,读到寄存器中,只能填补低8位,而剩下的高24位,就需要进行“整型提升”了。
左移和右移
<<
左移:最高位丢弃,最低位补0
>>
右移:
- 无符号数:最低位丢弃,最高位补0(逻辑右移)
- 有符号数:最低位丢弃,最高位补符号位(算术右移)
如何理解“丢弃”?
基本理解链:
<<
或者>>
都是计算,都要在CPU中进行,可是参与移动的变量,是在内存中的。所以需要先把数据移动到CPU中的寄存器中再进行移动。那么在实际移动的过程中,是在寄存器中进行的,即大小固定的单元内,那么,左移右移一定会有位置跑到==“外边”==的情况。
深度理解左移和右移
看上图,可以得出结论:
左移:无脑补0
右移:先判断是算术右移还是逻辑右移。判定依据:看自身类型,和变量的内容无关。