sizeof 运算符在以下代码片段中的行为如何?

How does sizeof operator behaves in below code snippet?

请解释以下代码段的 OP:

int *a="";
char *b=NULL;
float *c='[=10=]' ; 
printf(" %d",sizeof(a[1])); // prints 4 
printf(" %d",sizeof(b[1])); // prints 1
printf(" %d",sizeof(c[1])); // prints 4

编译器将 a[1] 解释为 *(a+1),所以 a 有一些地址,现在它提前 4 个字节,然后它会有一些垃圾值,所以 OP 4 个字节如何,即使我做了 a[0] ,它仍然打印 4 ,虽然它是一个空字符串,那么它的大小为什么是 4 个字节?

在这里我们找出指针指向的变量的大小,所以如果我说 a[1] 的大小,它意味着 *(a+1) 的大小,现在 a 有 a 的地址字符串常量,它是一个空字符串,在我对该地址执行 +1 后,它向前移动 4 个字节,现在它在某个新地址,现在我们如何知道这个值的大小,它可以是整数、字符或float 什么的,怎么得出这个结论?

sizeof 运算符发生在编译时(VLA 除外)。它查看的是表达式的类型,而不是实际数据,所以即使是这样的东西也能工作:

sizeof(((float *)NULL)[1])

并给你一个浮点数的大小。在你的系统上是 4 个字节。

Live example

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

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

这一切都是静态完成的,即在运行时不会发生取消引用。这就是 sizeof 运算符的工作方式,除非您使用可变长度数组 (VLA),否则它必须在运行时工作。

这就是为什么您可以 sizeof 逃脱的原因:通过 NULL 指针和其他东西。

你应该还在为

找麻烦
int *a = "";

这毫无意义。我也真的不喜欢 c 初始化程序,但至少这是有道理的。

除一种情况外,sizeof 运算符不计算其操作数。

来自 C 标准(6.5.3.4 sizeof 和 alignof 运算符)

2 The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

在此代码段中

int *a="";
char *b=NULL;
float *c='[=10=]' ; 
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]的类型是float.

所以printf调用输出对应4,1,4.

但是调用中的格式说明符指定不正确。而不是 "%d" 必须有 "%zu" 因为 sizeof 运算符返回的值的类型是 size_t.

来自 C 标准的同一部分

5 The value of the result of both operators is implementation-defined, and its type (an unsigned integer type) is size_t, defined in <stddef.h> (and other headers).