文章目录
第一章 词法“陷阱”
1.1 = 不同于==
- =是赋值运算符
- ==是比较运算符
if (x = y)
foo();
实际上是将y的值赋给了x,然后检查是否为0,我们应该进行显式的比较
if( ( x = y) != 0 )
foo();
1.2 &和| 不同于 &&和||
- & 和 | :按位运算符
- && 和 || :逻辑运算符
1.3语法分析中的“贪心法”
- /、* 、=、只有一个字符长,称为单字符符号
- /* 、==、以及标识符,包含了多个字符,成为多字符符号
当C编译器读入一个字符’/‘后又跟一个字符’/ * ‘,那么编译器就要做出判断:是将其作为两个符号区别对待,还是合起来作为一个符号对待。
规则:每一个符号应包含尽可能多的字符。
-
除了字符串和字符常量,符号的中间不能嵌有空白(空格符、制表符、换行符)
-
/* 为一注释的开始
y = x/*p /* p原本指向除数,但是/*被认为是一段注释 的开始 */
y = x/ *p /* p指向除数 */
y = x/ (*p) /* p指向除数 */
1.4整形常量
- 010 和 10 的含义截然不同
1.5字符与字符串
- 用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。
对于采用ASCII字符的编译器而言,’a‘的含义与0141或者97严格一致。
-
用双引号引起的字符串, 代表的是一个指向无名数组的起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制值为零的字符**’\0’**初始化
-
‘yes’ 和 “ yes ” 的区别
- ’ yes ’ 的含义并没有准确的进行定义,大多数C编译器理解为“一个整数值,由‘y’,‘e’,‘s’所代表的整数值按照特定编译器实现中定义的方式组合得到”。
- “yes” 依次 包含‘y’、‘e’、‘s’ 和 空字符 ‘\0’ 的4个连续内存单元的首地址。
第二章 语法陷阱
2.1 理解函数声明
- 任何C变量的声明函数都由两部分组成:
- 类型
- 一组类似表达式的声明符
float ff()
ff()是一个返回值为浮点类型的函数。
float *pf
*pf是一个浮点数,pf是指向浮点数的指针。
float *g() , (*h)();
*g ()和 ( *h)()是浮点表达式。
*g():因为()优先级高于 * ,*g() = *(g())。g是一个函数,返回值类型是指向浮点数的指针。
float ( * h)():h是一个指向返回值为浮点类型的函数的指针。
(float (*)())
指向”返回值为浮点类型的 函数的指针“的类型转换符。
(*fp)()
- fp是一个函数指针,*** fp就是该指针指向的函数。**
- (*fp)() 就是调用该函数的方式,简写为fp()。
- 声明sigfunc函数:
void sigfunc( int );
- 声明一个指向sigfunc函数的指针变量,命名为sfp:
void (*sfp) ( int );
sfp指向sigfunc函数,而*sfp代表sigfunc函数。
2.2运算符优先级问题
if ( flag & flags != 0)
!=运算符优先级高于 &,所以上式被理解为 :
if ( flag & ( flags != 0))
r = hi << 4 + low ;
+优先级高于<<,所以上式被理解为 :
r = hi << ( 4 + low );
-
两种修改方式
r = (hi<<4) + low;
r = hi<<4 | low;
优先级 | 运算符 | 结合性 |
---|---|---|
1 | ( ) [ ] -> . | 自左向右 |
2 | ! ~ ++ – +(正) -(负) (type) * & sizeof | 自右向左 |
3 | * / % | 自左向右 |
4 | +(加) -(减) | 自左向右 |
5 | << >> | 自左向右 |
6 | <