1. 使用close函数出现bad file descriptor错误
出现这种错误一般是两次close导致,仔细检查代码,调用close关闭文件描述符后,应该将文件描述符置为0,避免重复调用close,切记切记。
2. 守护程序闪退问题
出现这个问题一般是两次释放同一块内存,仔细检查释放内存与指针赋值相关代码,释放内存后,应将指针置为NULL,避免重复调用close,切记切记。
3. 四字节对齐
4. 什么是四字节对齐
现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。
4.1 四字节对齐作用
定义结构体成员时应当注意四字节对齐,保证内存利用最大化。但要注意,在32位机中使用1字节或2字节对齐,反而会降低变量访问速度。因此需要考虑处理器类型。还应考虑编译器的类型。在VC/C++和GNU GCC中都是默认是4字节对齐。
5. 柔性数组
定义结构体时,最后一个成员定义为
struct test {
int a;
char b[0];
}
b[0]就称为柔性数组,使用
sizeof(struct test);
返回值为4,即b[0]不占用内存空间。
6. 数字转字符
C语言书籍上可能出现过如下代码将数字转为字符
int a = 0;
char b = a + '0';
这个操作有局限性,当a的值超过9的时候就会得到你意向不到的结果,
int a = 10;
char b = a + '0';
这个时候字符b的值为’:’
7. fork函数注意事项
fork函数用来产生一个子进程,而且会复制父进程的资源(包括打开的文件描述符,变量等),无论是在子进程还是父进程对打开的文件描述符都需要谨慎对待,调用close函数关闭文件描述符可能不会报错,但是删除文件的时候就会出问题。
8. 变参宏定义
C99定义了一种变参宏定义
#define LOG(format, ...) fprintf(stdout, format, __VA_ARGS__)
…表示可变参数列表,VA_ARGS在预处理中,会被实际的参数集(实参列表)所替换。
同时gcc还支持带可以变参数名的方式(注意:VC不支持,即在vs环境下无法使用):
#define LOG(format, args...) fprintf(stdout, format, args)
同样,args在预处理过程中,会被实际的参数集所替换。其用法和上面的方式一样,只是参数的符号有变。
9. 整数相除
C语言中,两个int型相除只能得到int型,若结果分子小于分母,则结果为0。必要时,将分子或者分母强转为float型,则结果为float型。
10. 屏蔽gcc编译函数未使用错误
函数定义了未使用在visual studio中,不会报错,但是使用gcc编译时就要报错,如下所示:
1 | warning: 'xxx_handler' defined but not used [-Wunused-function] |
这个时候需要添加一个编译标志如下
1 CFLAGS="$CFLAGS -Wno-unused-function"
添加上这个标志以后,就不会报错了,常见标志可以参考gcc官网,要特别注意的是no这个标志,如果编译出现其他类似错误,又不想改代码,就可以加对应的标志,不同版本的gcc对于同一份代码可能出现错误。
11. 大端机与小端机
所谓大端就是指高位值在内存中放低位地址,所谓小端是指低位值在内存中放低位地址。比如0x12345678在大端机上是12345678,在小端机上是78563412,而一个主机是大端还是小端要看cpu类型以及运行在上面的操作系统。同一款cpu在不同的操作系统使用的大小端情况是不同的。个人理解0x1234是我们的书写习惯,转成二进制就是0001001000110100,读数从右往左读,所以0100是低位值,0001是高位值,在计算机中,内存地址增长方向是从左到右,所以左边是低位地址,右边是高位地址,如果计算机的低位地址存的是书写习惯的高位值,那么就是小端机,大小端机对单字节没影响。
12. 主机字节序与网络字节序
主机字节序就是大端序与小端序,网络字节序与大端序相同。在编写网络相关代码时,需要使用函数转换字节序,比如htons,htonl,ntohs,ntohl。
13. 管道
管道是一种把两个进程之间的标准输入和标准输出连接起来的机制,从而提供一种让多个进程间通信的方法,pipe(无名管道)和fifo(命名管道)两种。管道为半双工通信方式,也就是说只能一端读,一端写。
14. 隐式类型转换
unsigned char类型变量左移8位,编译器会进行类型提升。
15. 屏蔽格式转换错误
ubuntu gcc编译报错:
1 format '%llu' excepts argument of type 'long long unsigned int', but argument 2 has type 'uint_64'[-Wformat=]
解决方法:在编译时添加-Wformat=0