请解释以下代码段的OP:
int *a="";
char *b=NULL;
float *c='\0' ;
printf(" %d",sizeof(a[1])); // prints 4
printf(" %d",sizeof(b[1])); // prints 1
printf(" %d",sizeof(c[1])); // prints 4
编译器将[1]解释为*(a + 1),所以a有一些地址,现在它前进4个字节,然后它会有一些垃圾值那么OP 4字节是怎么回事,即使我做了a [0],它仍打印4,虽然它是一个空字符串,那么它的大小是4字节呢?
这里我们找出指针指向的变量的大小,所以如果我说a [1]的大小,则表示大小为*(a + 1),现在a有一个字符串常量的地址这是一个空字符串,在我对该地址+1后,它前移4个字节,现在它在某个新地址,现在我们怎么知道这个值的大小,它可以是一个整数,一个字符或一个浮点数,什么,所以如何得出结论?
答案 0 :(得分:4)
除一种情况外,sizeof运算符不会计算其操作数。
来自C标准(6.5.3.4 sizeof和alignof运算符)
2 sizeof运算符产生其操作数的大小(以字节为单位) 可以是表达式或类型的带括号的名称。大小是 根据操作数的类型确定。结果是整数。 如果操作数的类型是可变长度数组类型,则计算操作数;否则,操作数不被评估和 结果是一个整数常量。
在此代码段中
int *a="";
char *b=NULL;
float *c='\0' ;
printf(" %d",sizeof(a[1])); // prints 4
printf(" %d",sizeof(b[1])); // prints 1
printf(" %d",sizeof(c[1])); // prints 4
表达式a[1]
的类型为int
,表达式b[1]
的类型为char
,表达式c[1]
的类型为{{ 1}}。
因此,float
会相应地调出printf
,4
,1
。
但是,调用中的格式说明符指定不正确。 4
必须"%d"
,而不是"%zu"
,因为sizeof
运算符返回的值的类型为size_t
。
来自C标准的同一部分
5两个运营商的结果价值都是实施定义的, 和其类型(无符号整数类型)是size_t ,定义于
<stddef.h>
(以及其他标题)。
答案 1 :(得分:3)
这都是静态完成的,即在运行时不会发生解除引用。这是sizeof
运算符的工作方式,除非您使用可变长度数组(VLA),然后它必须在运行时工作。
这就是为什么你可以通过sizeof
指针和其他东西逃脱NULL
。
你应该仍然遇到麻烦
int *a = "";
没有意义。我真的不喜欢c
初始化程序,但至少这是有道理的。
答案 2 :(得分:2)
sizeof
运算符在编译时发生(VLA除外)。它正在查看表达式的类型,而不是实际数据,所以即使这样的东西也可以工作:
sizeof(((float *)NULL)[1])
并给你一个浮点数的大小。你的系统上有4个字节。
尽管这看起来非常糟糕,但它的定义都很明确,因为实际上并没有发生任何取消引用。这是编译时对类型信息的所有操作。
答案 3 :(得分:1)
sizeof()
基于数据类型,因此虽然它的大小超出了分配给变量的内存范围,但它并不重要,因为它已经解决了在编译时而不是运行时。