C代码喜欢这个:
#include <stdio.h>
#include <unistd.h>
#define DIM(a) (sizeof(a)/sizeof(a[0]))
struct obj
{
int a[1];
};
int main()
{
struct obj *p = NULL;
printf("%d\n",DIM(p->a));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个对象指针p是NULL,所以,我认为这p->a是非法的.但是我已经在Ubuntu14.04中测试了这段代码,它可以正确执行.所以,我想知道为什么......
注意:原始代码在int a[0]上面,但我已经改变了,int a[1]因为每个人似乎都挂在那而不是实际的问题,这是:
sizeof(p->a)当表达式p等于时,表达式是否有效NULL?
Chr*_*eck 34
因为sizeof是编译时构造,所以它不依赖于评估输入.仅sizeof(p->a)根据成员的声明类型进行评估p::a,并在可执行文件中成为常量.所以p指向null的事实没有区别.
p播放的运行时值在表达式中绝对没有作用sizeof(p->a).
在C和C++中,sizeof是一个运算符而不是函数.它可以应用于type-id或表达式.除了表达式和表达式是一个可变长度数组(在C99中是新的)(如paxdiablo所指出的),表达式是一个未评估的操作数,结果与sizeof对照类型相同那个表达的代替.(Cf C11参考由于下面的paxdiablo,C++ 14工作草案5.3.3.1)
pax*_*blo 16
首先登场的,如果你想真正便携的代码,你不应该试图创建大小为零的数组1,当你在你原来的问题,现在固定的做到了.但是,因为这不是你的问题是否真正相关的sizeof(p->a)是有效的时候p == NULL,我们可以忽略它.
从C11部分6.5.3.4 The sizeof and _Alignof operators(我的大胆):
2/
sizeof运算符产生其操作数的大小(以字节为单位),该操作数可以是表达式或类型的带括号的名称.所述尺寸从类型确定操作数的.结果是整数.如果操作数的类型是可变长度数组类型,则计算操作数; 否则,不评估操作数,结果是整数常量.
因此,除非它是一个可变长度数组(您的示例不是),否则不会对操作数进行求值.只使用类型本身来确定大小.
1对于那里的语言律师,C11表示6.7.6.2 Array declarators(我的大胆):
1 /除了可选的类型限定符和关键字之外
static,[和]可以分隔表达式或*.如果它们分隔表达式(指定数组的大小),则表达式应具有整数类型.如果表达式是常量表达式,则其值应大于零.
但是,由于那是在约束部分(其中shall并且shall not不涉及未定义的行为),它只是意味着程序本身并不严格符合.它仍然被标准本身所覆盖.
此代码包含ISO C中的约束违规,原因如下:
struct obj
{
int a[0];
};
Run Code Online (Sandbox Code Playgroud)
任何地方都不允许使用零大小的数组.因此,C标准没有定义该程序的行为(虽然似乎有一些争论).
如果编译器实现非标准扩展以允许零大小的数组,则代码只能"正确运行".
必须记录扩展(C11 4/8),所以希望你的编译器文档定义它的行为struct obj(零大小的结构?)和值的值sizeof p->a,以及sizeof当操作数表示零大小的数组时是否评估其操作数.
| 归档时间: |
|
| 查看次数: |
2092 次 |
| 最近记录: |