关于 sizeof 溢出 size_t 的 C 标准

Posted

技术标签:

【中文标题】关于 sizeof 溢出 size_t 的 C 标准【英文标题】:C standard regarding sizeof overflowing size_t 【发布时间】:2020-01-05 22:43:45 【问题描述】:

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

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

【问题讨论】:

我将其视为未定义的遗漏 如果它没有被标准定义那么它是字面上未定义的行为,不是吗?哈哈。 gcc 拒绝sizeof(double[SIZE_MAX]); 【参考方案1】:

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

在 C 2018 7.19 2 中,标准规定 size_t“是 sizeof 运算符结果的无符号整数类型”。这告诉我们关于 type size_t 的信息,而不是关于在计算过程中可能出现的 values。在 5.2.4 中,该标准认识到 C 实现必然有限制,并且它们必须在不同点分解。

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

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

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

【讨论】:

根据this参考:“size_t可以存储任何类型(包括数组)理论上可能的对象的最大大小。” @Ayxan:那个引用是错误的。我在回答中引用了 C 标准,它是权威的。 在您的结论中使用广为人知的短语“未定义的行为”是否合适? @ryyker:我会犹豫是否要使用它。正如 C 标准所定义的,“未定义的行为”是绝对的;这意味着 C 标准对行为没有任何要求。 sizeof(double[SIZE_MAX/sizeof(double) + 1]) 确实可能是这种情况,但我认为最好将其视为 C 委员会忽视解决的问题,而不是委员会决定应该未定义的问题。 (另外,我不确定这句话是否很好理解。许多人似乎将其视为您必须避免的行为,但这与许多合法的 C 扩展不一致。) “未定义的行为在本国际标准中以“未定义的行为”一词或省略任何明确的行为定义来表示。” (C18 4 p2)。否则,我认为这涵盖了问题。

以上是关于关于 sizeof 溢出 size_t 的 C 标准的主要内容,如果未能解决你的问题,请参考以下文章

size_t总结

[c/c++] size_t是什么

如何定义自定义跨平台 size_t 类型?

unsigned int 与 size_t

C语言中sizeof的用法

c语言的一些小细节