提问人:Some Name 提问时间:10/28/2023 最后编辑:Some Name 更新时间:10/28/2023 访问量:191
计算长数组SIZE_MAX元素的大小
Evaluating sizeof long array of SIZE_MAX elements
问:
请考虑以下代码:
#include <stdio.h>
#include <limits.h>
#include <inttypes.h>
#include <stddef.h>
int main(){
size_t cnt = SIZE_MAX;
size_t sz = sizeof(long[cnt]);
printf("%zu\n", sz);
}
6.5.3.4/p2
:
如果操作数的类型是可变长度数组类型,则 对操作数进行评估;否则,不会计算操作数,并且 result 是一个整数常量。
问题是,这种太大的评估是否定义得当?由于是,该标准保证整数溢出具有明确定义的行为(与可能引发实现定义信号的情况不同)。sizeof
size_t
unsigned
unsigned
signed
我感到困惑的主要问题是
size_t sz = sizeof(long[SIZE_MAX]); //error: size of unnamed array is too large
甚至不编译 Godbolt 实时示例
答:
如果操作数的类型是可变长度数组类型,则计算操作数;否则,不会计算操作数,并且结果为整数常量。
是的,它定义明确。它在运行时对可变长度数组执行计算。结果大也没关系。sizeof(element)*number_of_elements
Barmar 正确地提到:
虽然它可能定义得很好,但它可能没有用。
评论
size_t == unsigned long
6.5.3.4/p5
size_t
是必须足够大以容纳实现中最大可能对象的大小的类型。所以它是明确的。
但是,如果对象的实际计算大小(假设为不定式整数大小)>则无法在程序中创建或使用该对象。那么它就完全没用了。SIZE_MAX
评论
sizeof(long[SIZE_MAX])
element_size * element_count
size_t
sizeof (long[SIZE_MAX])
不会编译,因为尝试形成类型是违反约束的。从 C6.2.5 标准草案的 §28 23 开始:long[SIZE_MAX]
完整类型的大小应小于或等于 。
SIZE_MAX
相关约束未列在“约束”标题下,因此编译器不需要为此发出诊断。在这种情况下,GCC 和 Clang 都选择失败并发出错误消息,但更常见的是具有未定义的行为,因为它违反了显式约束子句之外的“shall”。但我认为,当尝试声明一个不支持的数组时,合理的实现将无法编译并出现这样的错误。sizeof (long[SIZE_MAX])
这种语言似乎没有出现在以前的标准中,但标准委员会确定“......所有这些都解释了当前的标准,即巨大的物体使行为隐含地未定义。委员会认为,这一变化不是引入一种未定义的行为,而是明确这一点的澄清。
评论
SIZE_MAX
”。sizeof(char[SIZE_MAX])
SIZE_MAX/2
SIZE_MAX/2+1
sizeof (long [SIZE_MAX])
我感到困惑的主要问题是它甚至没有编译size_t sz = sizeof(long[SIZE_MAX]); //error: size of unnamed array is too large
SIZE_MAX
是一个常量表达式,可以在翻译过程中进行计算;它是可以用 表示的最大值,因此编译器知道除 以外的任何类型的元素数组将超过字节并拒绝代码。它可以对值大于 的任何常量表达式执行此操作。size_t
SIZE_MAX
char
SIZE_MAX
SIZE_MAX / sizeof (long)
cnt
不是常量表达式,因此在运行时之前不会进行评估,并且编译器无法将其标记为问题。sizeof( long[cnt] )
那么会发生什么呢?
6.2.5 类型
...
9 有符号整数类型的非负值范围是相应无符号的子范围 整数类型,并且每种类型中相同值的表示形式相同。41) 计算 涉及无符号操作数永远不会溢出,因为无法用 生成的无符号整数类型是缩小模数,该数比最大数大 1 可以由结果类型表示的值。
所以,基本上,会给你一些由修改的价值。它不会是数组的大小(以字节为单位);它将是一些可以放入 .定义明确,但不是非常有用。size_t sz = sizeof( long[cnt] )
SIZE_MAX
size_t
评论
SIZE_MAX
long[cnt]
可能大于允许的数组类型。