为什么 C 允许对尚未创建的变量使用 sizeof 运算符?

Why does C allow the sizeof operator on a variable that hasn't yet been created?

考虑以下示例代码:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *a = malloc(sizeof *a);
    *a = 5;
    free(a);
    return 0;
}

在这个例子中,我在堆上分配整数a并将其初始化为5。这一行具体

int *a = malloc(sizeof *a);

是让我感到困惑的地方(sizeof *a 部分)。对我来说,这看起来像是我试图在创建变量之前获取变量的大小,但我发现这种初始化指针的风格非常普遍。当我用 clang 编译这段代码时,我没有收到任何错误或警告。为什么编译器允许这样做?据我所知,这类似于做类似

的事情
int a = a + 1;

之前没有任何 a 的声明。这会产生 clang -Wall main.c:

的警告
main.c:17:13: warning: variable 'a' is uninitialized when used
      within its own initialization [-Wuninitialized]
    int a = a + 1;

这行与 sizeof 的指针声明有何不同?

sizeof 运算符的操作数 不计算 除非它是可变长度数组。仅查看它以确定其类型。

此行为记录在 C standard 的第 6.5.3.4p2 节中:

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.

在这种情况下,它知道 *a 的类型为 int,因此 *a 不被求值并且 sizeof *asizeof(int) 相同。

在大多数情况下,sizeof 是一个 编译时 运算符。编译器只知道您传递给它的类型的大小。

其次,其实在malloc调用的时候,变量a其实已经被定义了。变量在初始化之前必须已经定义(和分配)。否则初始化值会写到哪里?


的问题
int a = a + 1;

不是说a不存在,而是你在[=16=中使用a的值是不确定的 ].

对于某些类型,不确定值可能包含 trap representation, and if that happens it leads to undefined behavior.


关于 sizeof 运算符的小提示:编译器本身在编译时评估的唯一一次 不是 variable-length arrays