云题海 - 专业文章范例文档资料分享平台

当前位置:首页 > c陷阱与缺陷学习笔记

c陷阱与缺陷学习笔记

  • 62 次阅读
  • 3 次下载
  • 2025/12/9 3:50:52

#include

void main(void) {

int c;

char buf[BUFSIZ]; setbuf(stdout,buf);

while((c = getchar()) != EOF) putchar(c); }

这个是不对的。buf最后一次被清空是在什么时候?答案是在main函数结束之后,作为程序交回控制给操作系

统之前C运行时库所必须进行的清理工作的一部分。但是在此之前buf已经被释放。

解决方法一是加上static 声明。也可以把buf声明完全移到main函数之外。第二种办法是动态分配缓冲区,

在程序中并不主动释放分配的缓冲区

5.4 使用erron检测错误

很多的库函数,特别是那些与操作系统有关的,当执行失败时会通过一个名称为errno的外部变量,通知 程序该函数调用失败。

下面的是错误的: /*调用库函数*/ if(errno)

/*处理错误*/

因为,在库函数调用没有失败的情况下,并没有强制要求库函数一定要设置errno为0,这样errno的值可能

就是前一个执行失败的库函数设置的值。 下面更正了,可还是错误的: errno = 0; /*调用库函数*/ if(errno) /*处理错误*/

库函数在调用成功时,既没有强制要求对errno清零,但同时也没有禁止设置errno。

下面才是对的:

/* 调用库函数 */ if(返回的错误值) 检查errno

5.5 库函数signal

从理论上说,一个信号可能在C程序执行期间的任何时刻上发生,甚至可能出现在某些复杂的库函数(如

malloc)的执行过程中。因此从安全的角度讲,信号的处理函数不应该调用上述类型的库函数。基于同样的原

因,从signal处理函数中使用longjump退出,通常情况下也是不安全的:因为信号可能发生在malloc 或者其它

库函数开始更新某个数据结构,却又没有最后完成的过程中。因此signal处理函数能够做的安全的事情,似乎

就只有设置一个标志然后返回,期待以后主程序能够检查到这个标志,发现一个信号已经发生。

然而,就算这样做也并不总是安全的。当一个算术运算错误引发一个信号时,某些机器在signal处理函

数返回后还将重新执行失败的操作。因此对于算术运算错误,signal处理函数的惟一安全、可移植的操作就是

打印一条出错消息,然后使用longjump或exit立即退出程序。

当一个程序异常终止时,程序输出的最后几行常常会丢失,原因是缓冲。

Chapter 6 预处理器

6.1 不能忽视空格

6.2 宏并不是函数

6.3 宏并不是语句

#define assert(e) ((void)((e)||_assert_error(_FILE_,_LINE_))) 6.4 宏并不是类型定义

我们没有办法在一个C表达式的内部声明一个临时变量。 避免副作用的一个办法就是再引入一个变量。

在某个上下文中本应需要函数而实际上却用了函数指针,那么该指针所指向的函数将会自动地被取得并替换这 个函数指针。

Chapter 7 可移植性缺陷

7.1 应对C语言标准变更 7.2 标识符名称的限制

c标准所能保证的只是,c实现必须能够区别出前6个字符不同的外部名称,且并没有要求区分大小写。 7.3 整数的大小

一个普通(int)整数足够大以容纳任何数组下标。

字符长度由硬件决定

7.4 字符是有符号整数还是无符号整数

若为有符号,则将其转为int时,应该同时复制符号位,而无符号,则填 0即可。 一个常见的错误是:如果c是一个字符变量,使用(unsigned)c就可得到与c等价的无符号整数。这是错误

的,因为在将字符c转换为无符号整数之前,c将先被转为int型,而此时可能得到非预期的结果。

正确的是使用语句(unsigned char)c,这样就直接转换。 7.5 移位运算符

如果被移位的对象长度是n位,那么移位计数必须大于或等于0,而严格小于n。

即使某些c实现将符号位复制 到空出的位中,有符号整数的向右移位运算也并不等于除以2的某次幂。

(-1)>>1这一般不可能为0,但(-1)/2一般为0.

7.5 内存位置0

NULL指针并不指向任何对象,只能用于赋值或比较运算。

7.7 除法运算的截断

q = a / b; r = a % b;

C 语言的定义只保证q*b+r==a,以及当a>=0且b>0时,保证|r|<|b|以及r>=0.最好避免a为负值。

7.8 随机数的大小

RAND_MAX

7.9 大小写转换

7.10 首先释放,然后重新分配

注意早期的C实现可以realloc一个已经free了的指示针。

7.11 一个例子

因为字符串常量可以用来表示一个字符数组,所以在数组名出现的地方都可以用字符串常量末端替换。 如:

\

-n可能溢出,因为最小负数的绝对值大于最大正数的绝对值。所以改亦正数的符号不会有问题,而改变

负数的符号则可能有问题。

void printnum(long n, void (*p)()) {

if(n<0) {

(*) ('-'); n=-n; }

if(n>=10)

printnum(n/10,p);

(*p)((int)(n) + '0'); }

上面的是有问题的。下面的才是对的: void printneg(long n, void (*p)()) {

long q; int r;

q = n / 10; r = n % 10; if(r>0) {r -= 10; q++; } if (n <= -10) printneg(q,p);

(*p)(\}

void printnum (long n, void (*p)()) {

if(n < 0) {

(*p)('-'); printneg(n,p); } else

printneg(-n,p);

搜索更多关于: c陷阱与缺陷学习笔记 的文档
  • 收藏
  • 违规举报
  • 版权认领
下载文档10.00 元 加入VIP免费下载
推荐下载
本文作者:...

共分享92篇相关文档

文档简介:

#include void main(void) { int c; char buf[BUFSIZ]; setbuf(stdout,buf); while((c = getchar()) != EOF) putchar(c); } 这个是不对的。buf最后一次被清空是在什么时候?答案是在main函数结束之后,作为程序交回控制给操作系 统之前C运行时库所必须进行的清理工作的一部分。但是在此之前buf已经被释放。 解决方法一是加上static 声明。也可以把buf声明完全移到main函数之外。第二种办法是动态分配缓冲区, 在程序中并不主动释放分配的缓冲

× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:10 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219
Copyright © 云题海 All Rights Reserved. 苏ICP备16052595号-3 网站地图 客服QQ:370150219 邮箱:370150219@qq.com