C语言开发的几个小经验总结

C语言开发的几个小经验总结

选择正确的整数数据类型

优先选择有符号整数

32位无符号整数的范围为0-2的32次方-1。
32为符号整数的范围为-2的31次方-2的31次方-1。
这里面的陷阱在于减法操作。

1
2
3
4
5
6
uint32_t a = 0;

if(a - 1 < 0){
//代码不会进入这里
....
}

这里a为无符号整数,a-1的结果会转化为无符号整数。

当然正确的做法是不使用默认类型转换。但人总有打盹的时候是不?

谨慎使用bool类型

新的C语言标准中是由bool类型的,编译器也有专有支持。

这里的问题是bool类型表现出一定的整数特性。

1
2
3
4
5
6
7
bool status = false;

status += 1; // status 为true

status += 1; // status 为true

status == 2 //false, 这时status的值仍为1

bool的实现,编译器会有差异。所以这里代码可能和你的编译结果不一样。

这里容易出错的地方有二:

  • 变量名没有数据类型的暗示,可能改为b_status会好很多.
  • 变量开始是两个值,后期需要支持三个值。
函数参数谨慎使用bool类型

函数参数有bool这类较窄的数据时,调用函数时提供完整的函数声明。
建议优先使用字长参数。

提供完整的函数声明

C语言调用函数时不需要提供函数声明,只要link时能找到同名符号就可以link成功。
首先不提供函数声明是不好的习惯。
因为没有正确的函数声明,编译器编译代码时会根据调用函数时提供的参数来生成参数入栈代码。这时候因为参数类型推断错误导致代码运行时失败。前面提到到函数参数使用bool类型就可能会导致这种问题。

sscanf直接返回到结构体导致数据溢出

1
2
3
4
5
6
7
8
9
10
11
typedef struct {
short a,
short b,
char c,
int d;
} T;

T t;
char *str = get_str();
sscanf(str, "%d", &(t.d));
sscanf(str, "%c", &(t.c)); //这里sscanf读出的内容为int类型,导致成员d的前三个字节被覆盖。

sscanf函数建议先读到临时变量中,再给struct结构成员赋值。

结语

上述经验只是最近参与开发的项目中遇到的比较隐蔽的问题。平时养成良好的编码习惯,上面的问题基本都能避免。