在C语言中,表达式中经常发生类型转换(type promotion, type conversion),由标准规定:
char,short)在算术操作之前会自动转换为int或unsigned int。示例:
unsigned short a = 65535; signed short b = -1; printf("%d\n", a + b); // 取决于转换!
建议:特别在处理位操作、数组长度、索引时,仔细检查操作数的类型,并避免隐式混合有符号和无符号类型。
下面的代码片段会输出什么?
unsigned int u = 1; int i = -2; printf("%d\n", u + i);
答案:变量i将被转换为unsigned int,最终值会变得非常大,因为底层结果为:1U + (unsigned int)-2U,这将产生接近UINT_MAX(4294967295)的数字。只有当printf以int格式化时,才会打印出负数,否则显示为垃圾值。
故事
在计算图像强度的平均值时,混淆了
int和unsigned int。负值通过unsigned错误传递,产生巨大的数字,导致图像缓冲区溢出。
故事
在嵌入式固件中,通过
size_t计算字符串长度,同时通过int索引数组。在检查数组越界条件时,比较int i >= size_t len,这对长字符串破坏了逻辑,并在比较不同类型时导致了漏洞(size_t是无符号的)。
故事
一位金融项目的开发者通过
%计算负数的余数,忘记了负操作数的结果符号取决于实现。在一个环境中,结果是正数,而在另一个环境中为负数,这导致计算周期性“偏移”。