&a 与 *a 的大小

Sizeof &a vs *a

我彻底搜索但找不到解决方案: 假设sizeof(int) = 4,我们定义:

int a[10] = {0};

下面的输出是什么:
1. sizeof(&a)
2. sizeof(*a)
3. sizeof(a)

我知道 sizeof(a) 等于 sizeof(int) * 10 = 40
我也明白 *a 实际上是数组中的第一个元素,因此 sizeof(*a) 实际上是驻留在其中的 int 的大小,即 4.

但是,在运行代码之后,我不明白为什么&a的大小是8。 我知道'&'运算符returns变量的地址是a,但是为什么sizeof的地址是8

地址的大小取决于您的体系结构,与 int 本身的大小没有直接关系。所以你的情况是 8,这看起来很正常(64 位)。

理解这一点的关键是知道数组通常 "decay" 指向第一个元素的指针,只要它们在表达式中使用。 除了一些特殊情况。 C标准(C17 6.3.2.1/3)中数组衰减的规则和例外情况:

Except when it is the operand of the sizeof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.

正如我们所见,sizeof& 是规则的例外。

这意味着 sizeof(&a) 中的 a 不会衰减为指针。我们可以知道这一点,因为 sizeof 和一元 & 都是一元运算符,具有相同的优先级,但具有从右到左的运算符结合性。这意味着 &a 首先被解释,并且在使用 & 时没有数组衰减。

这样我们就得到了数组的地址。在您的例子中,类型为 int(*)[10] 的 int 指针的大小。指针的大小与 int 的大小无关,但在 32 位和 64 位系统上很可能分别是 4 或 8 字节。

sizeof(*a) 的情况下,就像在 &a 的情况下一样,一元运算符的从右到左的结合性意味着 *a 首先被解释。因此,在应用 sizeof 之前,数组确实会衰减为指向第一个元素的指针。所以*a给出了第一个元素的大小,也就是一个int.

的大小

最后在 sizeof(a) 的情况下没有数组衰减,因为 asizeof 一起使用并且没有其他运算符存在。这意味着我们得到了整个数组的大小。

sizeof &a == sizeof (int (*)[10]) // pointer to 10-element array of int
sizeof *a == sizeof a[0] == sizeof (int)
sizeof  a == sizeof (int [10])

并且只是为了完整

 sizeof &a[0] == sizeof (int *)

所有这些大小都取决于底层平台。指针类型大小不依赖于指向类型的大小(intint * 的大小之间没有关系)。不同的指针类型可能有不同的大小——唯一的要求是:

  • char *void * 具有相同的大小和对齐方式;
  • 指向限定类型​​的指针与其非限定等价物具有相同的大小和对齐方式(例如,sizeof (const int *) == sizeof (int *)
  • 所有 struct 指针类型具有相同的大小和对齐方式;
  • 所有 union 指针类型具有相同的大小和对齐方式;

在您可能遇到的任何现代桌面或服务器系统(阅读:x86)上,所有对象指针类型都具有相同的大小和对齐方式。请注意,有些古怪的架构可能并非如此。