C语言sizeof与数组遍历问题:为何需类型转换才得预期结果?
问题分析:sizeof与有符号/无符号类型比较的陷阱
问题代码与现象
第一段代码:
#include <stdio.h> #define TOTAL_ELEMENTS (sizeof(arr))/sizeof(arr[0]) int arr[] = {23, 34, 12, 17, 204, 99, 16}; int main() { int d; printf("%zu\n", TOTAL_ELEMENTS); for (d = -1; d <= (TOTAL_ELEMENTS - 2); d++) { printf("%d ", arr[d + 1]); } return 0; }
编译运行后仅输出7,未按预期输出数组所有元素。
第二段代码仅修改循环条件,将(TOTAL_ELEMENTS - 2)强制转换为int类型,即可得到预期输出:
// 修改后的循环条件 for (d = -1; d <= (int)(TOTAL_ELEMENTS - 2); d++) {
核心原因分析
你忽略了无符号类型的溢出与比较规则:
sizeof的返回值是size_t类型,这是一个无符号整数类型。TOTAL_ELEMENTS值为7,减2后结果仍为size_t类型(值为5)。- 当有符号整数
d(初始值为-1)与无符号整数比较时,C语言的隐式类型提升会把有符号整数转换为无符号整数。 - 有符号整数
-1转换为无符号size_t时,会变成该类型的最大值(比如32位系统下是0xFFFFFFFF),这个值远大于5,因此d <= (TOTAL_ELEMENTS - 2)的初始条件直接不成立,循环根本不会执行。
关键知识点总结
size_t是无符号类型,所有涉及sizeof的计算结果都属于无符号范畴,和有符号整数运算、比较时需格外注意。- 有符号整数转无符号整数时遵循模运算规则:负数会被转换为对应无符号类型的最大值加1再加上该负数(例如
-1转size_t就是UINT_MAX + 1 + (-1) = UINT_MAX)。 - 不同符号类型比较时,有符号数会被提升为无符号数,这会导致负数的比较逻辑完全不符合直觉。
内容的提问来源于stack exchange,提问作者Bhargav Patil
相关产品推荐
相关产品推荐

