sizeof运算符如何在下面的代码片段中表现?

时间:2017-03-24 15:35:38

标签: c sizeof

请解释以下代码段的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个字节,现在它在某个新地址,现在我们怎么知道这个值的大小,它可以是一个整数,一个字符或一个浮点数,什么,所以如何得出结论?

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会相应地调出printf41

但是,调用中的格式说明符指定不正确。 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个字节。

Live example

尽管这看起来非常糟糕,但它的定义都很明确,因为实际上并没有发生任何取消引用。这是编译时对类型信息的所有操作。

答案 3 :(得分:1)

sizeof()基于数据类型,因此虽然它的大小超出了分配给变量的内存范围,但它并不重要,因为它已经解决了在编译时而不是运行时。