《c陷阱与缺陷》读书笔记

先来一个热身:

#define ABC(x) x*x

   #include"stdio.h"

   main()

   {int a=3,b;

    b=ABC(a+1);

    printf("b=%d", b); }

输出是7,原因是宏只是简单替换,不包括括号

 

一、词法陷阱

1.            c编译器是从左到右读入字符的(大嘴法)

 

2.            int a = 0111;//代表8进制数,十进制是73

3.            int i = 'ab';//代表将字符a和b的ascll码赋值给i(i通常有多个字节,而字符型1个字节)

 

4.            %d整型输出,%ld长整型输出,

%o以八进制数形式输出整数,

%x以十六进制数形式输出整数,

%u以十进制数输出unsigned型数据(无符号数)。

%c用来输出一个字符,

%s用来输出一个字符串,

%f用来输出实数,以小数形式输出,

%e以指数形式输出实数,

%g根据大小自动选f格式或e格式,且不输出无意义的零。

 

5.            对于 /*/*/0*/**/1,

支持注释嵌套的编译器(注释里可以有注释)解释为1

不支持注释嵌套的编译器(/*后面都是注释直到*/)解释为0*1

c的编译器一般不支持嵌套注释,原因也许是这样更复杂(既然是注释,注释内的所有文本都被视为注释而被编译器无视之,凭什么注释内的/*,也就是注释开始符号要特殊对待呢?)

 

二、       语法陷阱

1.            int *g(),(*h)();//g是一个返回值类型为指向整形的指针的函数,h是一个函数指针,其指向的函数的返回值是int型

 

2.            ANSI C标准允许在用函数指针fp调用函数时,把(*fp)()简写为fp()

 

3.            void (*fp)();//定义一个函数指针,其指向一个返回值为void的函数

(void (*)() )0将常数0转型为“指向返回值为void的函数的指针”

(* (void (*)() )0)();//调用一个首地址为0的函数,0被转换成了“指向返回值为void的函数的指针”,并以(*fp)()的方式调用

 

4.            逻辑运算符包括与、或、非,赋值运算符优先级仅比“,”要高,且是从右到左

5.            从右到左的还有有高优先级的!、~、++、--、-、(type)*、&、sizeof以及赋值运算符=

 

6.            *buf++ = c;//先++后*

 

7.            逗号运算符是逗号分开的表达式的值分别结算,但整个表达式的值是最后一个表达式的值。

 

8.            switch语句中记得break,也有故意不break的,例如:

case 减:

         num= -num;

case 加

         ...

 

9.            f();//调用函数

f;//计算函数f的地址,但不调用

 

三、       语义陷阱

1.            a[i]==*(a+i)==*(i+a)==i[a]//(相当神奇)

i[4][7]==*(i[4]+7)==*(*(i+4)+7)

 

2.            int (*a)[10];//定义一个指向数组的指针,该数组拥有10个int型元素

 

3.            为字符串malloc内存时,要比原句子多申请一个字节(因为字符串以'\0'结尾)

 

4.            尽量用for(i = 0; i < 10; i++)而不用小于等于9。原因是10-0=10相当于元素个数;元素个数为0时就是“i<0”

 

5.            y[i++] = x[i]的行为不确定,根据编译器而异

 

四、       连接

1.            最好对函数进行声明并在声明时明确参数和返回值的类型,否则会默认判断为int或者double

 

五、       预处理器

1.            宏是直接替代,必须加各种括号来预防优先级问题,如#define abs() ((x>=0)?(x):-(x))

 

2.            对于#define abs(x) x>0?x:-x,有abs(a)+1展开后为a>0?a:-a+1

 

3.            宏定义可以以“\”作为换行,例如:

#define MAX(a,b) \

((a) <(b) ? (b) : (a))

 

char buf[128];

strcpy(buf, "1234567890ab "

"cdefg ");

等同于:

char buf[128];

strcpy(buf, "1234567890abcdefg");

 

4.            对于#define T1 int *,T1 a,b相当于 T1 * a,b;

 

六、       可移植性缺陷

1.            char会被转换成int型再做运算,具体行为不确定

2.            在确定非负的情况下,右移比除的执行速度快

3.            在C语言中余数的符号是和被除数的符号相同,即(-10)%3==-1; 10%(-3)==1;

4.            让变量反号时注意范围,通常负数比正数范围大

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值