C语言进阶:C陷阱与缺陷(读书笔记三)

如果读起来感觉很吃力,那我推荐你读一读书,书上的例子比较多,看着能轻松一点,老鸟看起来应该不是很难,作为复习一下,应该还不错,5min可以看完。

C语言进阶

  • 五、 库函数
    • 1、 返回整数的getchar函数
    • 2、更新顺序文件
    • 3、缓冲输出与内存分配
    • 4、 使用errno检测错误
    • 5、 库函数signal
  • 六、 预处理器
    • 1、 不能忽视宏定义中的空格
    • 2、 宏并不是函数
    • 3、 宏并不是语句
    • 4、 宏并不是类型定义

五、 库函数

1、 返回整数的getchar函数

尽量使用系统头文件
1、返回整数的getchar函数

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

这个存在三种可能:
1)某些合法的输入字符在被”截断“后使得c的取值与EOF相同,程序将在文件复制的中途终止。
2)c取不到EOF这个值,程序将陷入死循环。
3) 因为巧合可以工作。

2、更新顺序文件

访问文件时,不能同时进行读写操作,如果想要同时进行,必须插入fseek函数调用。
类似:

read
seek
write
seek

第二次的seek改变文件状态,使得下一次文件可以正常读写。

3、缓冲输出与内存分配

setbuf(stdout,buf);可以将输出暂存起来,然后大块写入
使用时,为了避免错误,可以用两种方法:
1)将缓冲区成为静态数组,例如 static char buf[BUFSIZE];setbuf(stdout,buf);
2)动态分配缓冲区,例如:setbuf(stdout,malloc(BUFSIZE));

4、 使用errno检测错误

正确使用errno的方式

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

5、 库函数signal

signal(signal type,handler function);
捕获异步事件的一种方式,信号非常复杂,而且具有一些从本质上而言不可移植的特性,我们要让signal处理函数尽可能简单。
例如: 打印一条错误消息,然后直接exit退出程序。

六、 预处理器

预处理器的重要性可以由两个主要的原因说明:
1)预处理器可以实现只需要改动一处数值,便可将用到该值的地方的所以地方都修改,将这个数定义为显式常量。
2)没有函数调用带来的系统开销

1、 不能忽视宏定义中的空格

1、不能忽视宏定义中的空格
例如:

#define  f  (x)  ((x)-1)

f(x) 代表 ((x)-1) 错误
f 代表 (x) ((x)-1) 正确
#define f(x) ((x)-1)
这样才能实现 f(x) 代表 ((x)-1)

2、 宏并不是函数

宏定义中最好把每个参数都用括号括起来,来避免错误。
例如

#define abs(x)  x>0?x:-x

abs(a)+1 会得到 a>0 ? a : -a+1
但我们的本意不是这样。
如果宏实现比较复杂,那么尽量使用函数来实现。
宏的展开可能会产生庞大的展开式。

3、 宏并不是语句

这里的例子有点晦涩,不知如何表达,只是记住宏并不能直接当作语句去使用,并且要注意分号即可。

4、 宏并不是类型定义

#define FOOTYPE	struct foo 
FOOTYPE a;
FOOTYPE b,c;

这样我们只需要修改一行代码就可以改变abc的类型,但是我们并不推荐如此使用,最好还是使用类型定义

typedef  struct foo   FOOTYPE;

C陷阱与缺陷(读书笔记一)
C陷阱与缺陷(读书笔记二)
C陷阱与缺陷(读书笔记四)
C陷阱与缺陷(读书笔记总)

你可能感兴趣的:(C语言进阶,c语言,开发语言)