首页 > 解决方案 > 关于 sizeof 溢出 size_t 的 C 标准

问题描述

这是未定义的行为吗?标准的相关部分就不多说了。

size_t n = SIZE_MAX / sizeof(double) + 1;
size_t m = sizeof(double[n]);

标签: clanguage-lawyersizeofvariable-length-array

解决方案


C 标准没有明确声明该size_t类型足以处理所有对象或类型的大小,尤其是对于未实际实例化的假设类型。

在 C 2018 7.19 2 中,标准说size_t“是 sizeof 运算符结果的无符号整数类型”。这告诉我们类型 size_t,而不是计算过程中可能出现的值。在 5.2.4 中,该标准承认 C 实现必然有限制,并且它们必须在不同的点上崩溃。

7.19 4 说“用于size_t并且ptrdiff_t不应具有大于的整数转换等级的类型,signed long int除非实现支持足够大的对象以使其成为必要。” 这重申了我们size_t能够表示所有支持对象的大小的愿望,特别是因为它暗示了一个对象的存在使得size_t能够表示它是“必要的”,但这并不是size_t必须这样做的明确声明,它也不适用于可以描述但不能实例化为对象的假设类型。

如果我们要评估n * sizeof(double),我们知道结果: 6.2.5 9 说“涉及无符号操作数的计算永远不会溢出,因为无法用生成的无符号整数类型表示的结果会以比最大值大一的数字为模减少可以由结果类型表示的值。” 但是,对于sizeof(double[n]),这并不完全清楚,因为尽管n它是无符号的,但它不是 的直接操作数sizeof,在此计算无法表示的结果。标准没有明确告诉我们这样做的结果sizeof将以同样的方式减少。

因此,C 标准不涵盖此操作。


推荐阅读