当涉及到预增量或后增量时,我对右值的概念有一些疑问(可能是误解)。考虑以下 C 程序:
#include <stdio.h>
int main() {
int a[10];
int *ptr = a;
printf("%d", *++ptr);
return 0;
}
在这里,在
*++ptr
表达式中,首先评估++ptr
,它返回a[1]
的地址,这是一个右值。我的问题是,当我们随后使用 *
运算符取消引用该右值(地址)时,系统如何知道要获取多少字节的内存?因为 ++ptr
只是一个右值,无法从右值知道它指向什么类型的数据(地址/常量)。
相反,当我们做像
*ptr
这样的事情时,系统知道取4个字节或2个字节(取决于int
的大小)因为ptr
和*ptr
都被视为左值和系统知道ptr
指向的数据类型。
你能消除我对此的误解吗?
右值确实有一个类型——在前缀(和后缀)递增和递减运算符的情况下,该类型与操作数的类型相同。所以,如果
ptr
声明为int *ptr;
,那么++ptr
的结果类型也是int*
。
如果右值没有类型,那么数组访问将毫无意义,因为表达式
a[i]
(其中 a
是 T
类型的数组)是 完全等同于 *(a + i)
,其中如果a + i
操作的右值结果保持第一个(在这种情况下)操作数的类型(将被视为指向数组第一个元素的指针, 因此 T*
).不过,当使用运算表达式的结果作为类型时,有一些“陷阱”。在下面的代码中,我们可以看到++c
的结果类型是(就像
c
本身一样)achar
;然而,c + 1
的结果类型是一个 int
(在我的平台上,它的大小是 4 个字节):#include <stdio.h>
int main()
{
char c = 42;
printf("%zu %zu %zu\n", sizeof(c), sizeof(++c), sizeof(c + 1)); // Shows: 1 1 4
return 0;
}