应用于数组名称的 sizeof 与指向数组第一个元素的指针
sizeof applied to the name of an array vs a pointer to the first element of the array
假设我声明int v[]={1,2,3,4,5};
我被告知 v
是指向 v
数组中第一个元素的指针。当我调用 apply sizeof
到 v
时,它 returns 20,我知道是 5*sizeof(int)
,因为数组中有 5 个元素。
v+0
也是指向数组第一个元素的指针,但是sizeof(v+0)
是4.
为什么 sizeof(v)
=20 而 sizeof(v+0)
=4?
我希望 sizeof(v)
也返回 4,因为 v
是一个指针,但它不知何故还包含有关存储在数组中的元素数量的信息。对此有何解释?
I would expect that sizeof(v) also returned 4
没有.
首先,v
不是一个指针,它是一个数组。数组衰减 为指针。在 What is array decaying?
中阅读更多内容
当您调用 sizeof(v)
时,您将获得数组的大小(以字节为单位)。
20 等于 4 * 5 = 4 * N,其中 N 是数组中元素的数量。
此外请注意,在您的系统中,int 的大小为 4 个字节。
指针和数组密切相关,但并不等同。
在大多数情况下,数组的名称将衰减 指向第一个元素的指针。然而,有一些情况不会发生这种情况,特别是当数组是 sizeof
运算符的操作数时(是的,它是一个运算符,而不是函数)。
因此在表达式 sizeof(v)
中,名称 v
不会衰减,因为它是 sizeeof
运算符的操作数。结果,给出了整个数组的大小。相反,sizeof(v+0)
是不同的,因为 v
是 +
运算符的操作数。在这种情况下,v
实际上会衰减为指针并执行指针运算。这给出了一个 int *
类型的表达式,它是 sizeof
.
的操作数
I have been taught that v
is a pointer to the first element in the v
array.
你被错误地教导了。 v
不是指针 - 没有 space 因为指针被具体化为数组的一部分。你得到的是这样的:
+---+
v: | 1 | v[0]
+---+
| 2 | v[1]
+---+
| 3 | v[2]
+---+
| 4 | v[3]
+---+
| 5 | v[4]
+---+
和不是这个:
+---+
v: | |
+---+
|
|
V
+---+
| 1 | v[0]
+---+
| 2 | v[1]
+---+
| 3 | v[2]
+---+
| 4 | v[3]
+---+
| 5 | v[4]
+---+
除非它是 sizeof
或一元 &
运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,表达式 类型 "N-element array of T
" 将被转换 ("decay") 为类型 "pointer to T
" 的表达式,表达式的值将是数组第一个元素的地址。
当你写 foo( v )
或 printf( "%p\n", (void *) v)
甚至 v[i]
时, 表达式 v
是从类型“int
的5元素数组”转换为"pointer to int
",表达式的值与&v[0]
相同。
但是,当您写入 sizeof v
时,该转换不会发生 - sizeof
计算为整个数组中的字节数 (5 * sizeof (int)
)。同样,表达式 &v
的类型是 int (*)[5]
(指向 int
的 5 元素数组的指针),而不是 int **
。
这就是为什么 sizeof v
产生 20,而 sizeof (v + 0)
产生 4 - 在第二种情况下,v
是 而不是 的操作数sizeof
,表达式 (v + 0)
是sizeof
的操作数。在表达式 (v + 0)
中,v
衰减为类型 int *
。请注意,如果您编写 sizeof v + 0
- sizeof
的优先级高于加法运算符 +
,您将得到不同的结果,因此该表达式将被解析为 (sizeof v) + 0
。
sizeof v
= 20
因为在您的系统中有 5
个元素,每个元素的大小为 4
字节。至此一切都正确。但是后来你提到 v
是一个指针。是这样吗?
没有。数组不同于指针。为什么会有混淆?
在 sizeof(v+0)
的上下文中,这将解释一下:
您可能会从标准(指针算术下)中找到两件有用的东西§6.5.6.2
For addition, either both operands shall have arithmetic type, or one
operand shall be a pointer to a complete object type and the other
shall have integer type. (Incrementing is equivalent to adding 1.)
还有来自§6.5.6.7
For the purposes of these operators, a pointer to an object that is
not an element of an array behaves the same as a pointer to the first
element of an array of length one with the type of the object as its
element type.
所以这里 v
衰减为指针作为 +
的操作数而不是 sizeof
运算符的操作数。事实上,当用作 sizeof
运算符的操作数时,数组 不会 退化为指针。现在 sizeof
指针变量在 yoru 系统上是 4
字节。这就是你看到的。
长话短说数组不是指针。它们不同。第二种情况可能会给您一种错误的印象,即他们是,或者即使您的老师说了,但事实并非如此。数组衰减为不使数组成为指针的指针。
假设我声明int v[]={1,2,3,4,5};
我被告知 v
是指向 v
数组中第一个元素的指针。当我调用 apply sizeof
到 v
时,它 returns 20,我知道是 5*sizeof(int)
,因为数组中有 5 个元素。
v+0
也是指向数组第一个元素的指针,但是sizeof(v+0)
是4.
为什么 sizeof(v)
=20 而 sizeof(v+0)
=4?
我希望 sizeof(v)
也返回 4,因为 v
是一个指针,但它不知何故还包含有关存储在数组中的元素数量的信息。对此有何解释?
I would expect that sizeof(v) also returned 4
没有.
首先,v
不是一个指针,它是一个数组。数组衰减 为指针。在 What is array decaying?
当您调用 sizeof(v)
时,您将获得数组的大小(以字节为单位)。
20 等于 4 * 5 = 4 * N,其中 N 是数组中元素的数量。
此外请注意,在您的系统中,int 的大小为 4 个字节。
指针和数组密切相关,但并不等同。
在大多数情况下,数组的名称将衰减 指向第一个元素的指针。然而,有一些情况不会发生这种情况,特别是当数组是 sizeof
运算符的操作数时(是的,它是一个运算符,而不是函数)。
因此在表达式 sizeof(v)
中,名称 v
不会衰减,因为它是 sizeeof
运算符的操作数。结果,给出了整个数组的大小。相反,sizeof(v+0)
是不同的,因为 v
是 +
运算符的操作数。在这种情况下,v
实际上会衰减为指针并执行指针运算。这给出了一个 int *
类型的表达式,它是 sizeof
.
I have been taught that
v
is a pointer to the first element in thev
array.
你被错误地教导了。 v
不是指针 - 没有 space 因为指针被具体化为数组的一部分。你得到的是这样的:
+---+
v: | 1 | v[0]
+---+
| 2 | v[1]
+---+
| 3 | v[2]
+---+
| 4 | v[3]
+---+
| 5 | v[4]
+---+
和不是这个:
+---+
v: | |
+---+
|
|
V
+---+
| 1 | v[0]
+---+
| 2 | v[1]
+---+
| 3 | v[2]
+---+
| 4 | v[3]
+---+
| 5 | v[4]
+---+
除非它是 sizeof
或一元 &
运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,表达式 类型 "N-element array of T
" 将被转换 ("decay") 为类型 "pointer to T
" 的表达式,表达式的值将是数组第一个元素的地址。
当你写 foo( v )
或 printf( "%p\n", (void *) v)
甚至 v[i]
时, 表达式 v
是从类型“int
的5元素数组”转换为"pointer to int
",表达式的值与&v[0]
相同。
但是,当您写入 sizeof v
时,该转换不会发生 - sizeof
计算为整个数组中的字节数 (5 * sizeof (int)
)。同样,表达式 &v
的类型是 int (*)[5]
(指向 int
的 5 元素数组的指针),而不是 int **
。
这就是为什么 sizeof v
产生 20,而 sizeof (v + 0)
产生 4 - 在第二种情况下,v
是 而不是 的操作数sizeof
,表达式 (v + 0)
是sizeof
的操作数。在表达式 (v + 0)
中,v
衰减为类型 int *
。请注意,如果您编写 sizeof v + 0
- sizeof
的优先级高于加法运算符 +
,您将得到不同的结果,因此该表达式将被解析为 (sizeof v) + 0
。
sizeof v
= 20
因为在您的系统中有 5
个元素,每个元素的大小为 4
字节。至此一切都正确。但是后来你提到 v
是一个指针。是这样吗?
没有。数组不同于指针。为什么会有混淆?
在 sizeof(v+0)
的上下文中,这将解释一下:
您可能会从标准(指针算术下)中找到两件有用的东西§6.5.6.2
For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to a complete object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)
还有来自§6.5.6.7
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
所以这里 v
衰减为指针作为 +
的操作数而不是 sizeof
运算符的操作数。事实上,当用作 sizeof
运算符的操作数时,数组 不会 退化为指针。现在 sizeof
指针变量在 yoru 系统上是 4
字节。这就是你看到的。
长话短说数组不是指针。它们不同。第二种情况可能会给您一种错误的印象,即他们是,或者即使您的老师说了,但事实并非如此。数组衰减为不使数组成为指针的指针。