mrs*_*ith 16 c arrays sizeof c99 undefined-behavior
有一个众所周知的模式来计算数组长度:
int arr[10];
size_t len = sizeof(arr) / sizeof(arr[0]);
assert(len == 10);
Run Code Online (Sandbox Code Playgroud)
此模式适用于静态数组和常量大小的自动数组.它也适用于C99中的可变长度数组.
我想应用类似的想法来计算动态数组大小(以字节为单位):
size_t known_len = 10;
int *ptr = malloc(known_len * sizeof(int));
size_t size = known_len * sizeof(ptr[0]);
assert(size == known_len * sizeof(int));
Run Code Online (Sandbox Code Playgroud)
这比known_len * sizeof(int)
因为sizeof(ptr[0])
没有引用实际的数组元素类型更好.因此,它不需要代码的读者知道类型.
然而,我不清楚表达是否sizeof(ptr[0])
会导致不确定的行为.随着它扩大:
sizeof(ptr[0]) -> sizeof(*((ptr) + (0))) -> sizeof(*ptr)
Run Code Online (Sandbox Code Playgroud)
如果ptr
是,结果表达式是有问题的0
:
sizeof(*((int*) 0))
Run Code Online (Sandbox Code Playgroud)
根据C99标准:
(C99,6.3.2.3p3):"带有值的整型常量表达式
0
,或者这种表达式转换为类型void *
,称为空指针常量." 取消引用空指针是未定义的行为.(C99,6.5.3.2.p4)"如果为指针分配了无效值,则一元运算
*
符的行为未定义.87)"87):"一元运算
*
符解除引用指针的无效值中有一个空指针,一个与指向的对象类型不一致的地址,以及一个对象在其生命周期结束后的地址."
但是从未指明这种表达式的sizeof是否会导致未定义的行为.实际上,应该在编译时评估这样的sizeof.
我的问题是:
sizeof(ptr[0])
当类型ptr
已知并且值ptr
不知道时,表达式是否可以在代码中使用?hac*_*cks 17
该表达式ptr[0]
将不会被评估sizeof(ptr[0])
.大小将通过使用ptr[0]
编译时的类型来确定.
的
sizeof
操作者产生其操作数的大小(以字节为单位),其可以是表达或类型的括号名称.大小由操作数的类型确定.结果是整数.如果操作数的类型是可变长度数组类型,则计算操作数; 否则,不评估操作数,结果是整数常量.
这意味着,没有未定义的行为.
das*_*ght 11
这不会导致未定义的行为.
除了采用可变长度数组的大小外,sizeof
还有一个编译时常量表达式.编译器处理表达式以确定其类型,而不生成在编译时评估表达式的代码.因此,at ptr[0]
(未初始化指针)的值根本不重要.
而且,如果你想分配十个整数,你应该这样调用malloc
:
int *ptr = malloc(known_len * sizeof(ptr[0]));
Run Code Online (Sandbox Code Playgroud)
否则,您将分配十个字节,这对于存储十个整数而言太小.请注意,在上面的表达式中ptr
,在调用时未初始化,这完全没问题sizeof
.