本文为个人读书笔记,仅供记录学习过程中遇到的日后需要留意的问题,如有相关版权问题请及时通知作者。
注释
编译器会用空格代替注释部分
块注释不能嵌套
/与*之间没有空格,就会被当做注释的开始
注释的基本要求
全局数据必须要加注释
注释是对代码的提示,不是文档
注释代码段时应注重为何做,而不是怎么做
数值的单位一定要注释
接续符和转义符
\ 反斜杠 表示断行。编译器会将反斜杠剔除,跟在反斜杠后面的字符自动接续到前一行。反斜杠之后、下一行之前不能有空格
\ 反斜杠还表示转义字符。
单引号双引号
单引号引起的是字符常量,双引号引起的是字符串常量
逻辑运算符
注意当逻辑算式已经确定值之后,将不再执行其他的运算。
位运算符
按位亦或可以实现不用第三个临时变量交换两个变量的值,不推荐。
左移右移
左移:左运算数的各二进制位向左移动右运算数位,高位丢弃,低位补0
右移:做运算数的各二进制位向右移动右运算数位。对于有符号数,右移时符号位移动。正数时,高位补0;负数时,符号位为1,最高位补0或补1取决于编译系统规定。
+号优先级高于左移右移。
左移右移的位数不能大于数据的长度,不能小于0
自加自减
int i=3;
(++i)+(++i)+(++i);
vc的结果是16。某些编译器结果是18 。
后自加:遇到,逗号 ;分好认为计算单位已结束,会自加。
贪心法:C语言规定,没一个符号应该包含尽可能多的字符。编译器将程序分解成符号的方法是,从左到右一个一个字符的读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能使一个符号的组成部分;如果可能,继续读入下一个字符,重复判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。这个处理的策略被称为“贪心法”。除了字符串与字符常量,符号的中间不能嵌有空白(空格、制表符、换行符等)
优先级
优先级 | 运算符 | 名称或含义 |
1 | [ ] | 数组下标 |
() | 圆括号 | |
. | 成员选择 对象 | |
-> | 成员选择 指针 | |
2 | - | 负号 |
(类型) | 强制类型转换 | |
++,-- | 自增自减 | |
* | 取值 | |
& | 取地址 | |
! | 逻辑非 | |
~ | 按位取反 | |
sizeof | 长度运算 | |
3 | / | 除 |
* | 乘 | |
% | 取余、模除 | |
4 | + - | 加减 |
5 | <<,>> | 左移右移 |
6 | >,>=,<,<= | 大于,大于等于,小于,小于等于 |
7 | ==,!= | 等于不等于 |
8 | & | 按位与 |
9 | ^ | 按位异或 |
10 | | | 按位或 |
11 | && | 逻辑与 |
12 | || | 逻辑或 |
13 | ?: | 条件运算符 |
14 | =,/=,*=,%=,+=,-=,<<=,>>=,&=,^=,|= | 赋值,除后赋值,乘后赋值,取余后赋值,加后赋值,减后赋值,左移后赋值,右移后赋值,按位与后赋值,按位异或后赋值,按位或后赋值 |
15 | , | 逗号运算符 |
容易出错的问题
优先级 | 表达式 | 错误结果 | 实际结果 |
.高于* | *p.f |
p所指对象的字段
f(*p).f
|
对p取f偏移,作为指针*
(p.f)
|
[ ]高于* | int *ap[ ] |
ap是指向int数组的指针
int (*ap)[ ]
|
ap是元素为int指针的数组
int *(ap[ ])
|
函数()高于* | int *fp() |
fp是个函数指针,所指函数返回int
int(*fp)()
|
fp是个函数,返回int*
int *(fp())
|
==和!=高于位运算 | (val&mask!=0) | (val&mask)!0 | val&(mask!=0) |
==和!=高于赋值符 | c=getchar()!=EOF | (c=getchar())!=EOF | c=(getchar()!=EOF) |
算术运算符高于位移 | msb<<4+lsb | (msb<<4)+lsb | msb<<(4+lsb) |
逗号优先级最低 | i=1,2 | i=(1,2) | (i=1),2 |