1. lvalue 和 rvalue 概念
在C语言中,有两个基础概念,分别是 lvalue 和 rvalue 。它们分别代表可左值(左边)和可右值(右边)的表达式。
lvalue 是指向有明确内存位置的对象,rvalue 是指没有固定内存位置的临时值。换句话说,lvalue 可以出现在赋值操作符左边,而 rvalue 只能出现在赋值操作符右边或函数调用中。
1.1 lvalue
lvalue 可以出现在赋值操作符的左边,它们是有明确内存地址的变量或对象。
lvalue 的一个重要的性质是其可以取地址,其地址可以被存储在指针变量中。
int a = 5;
int *pA;
pA = &a; //&表示取地址操作符,将变量a的地址赋给pA
上面这段代码中,a 是一个 lvalue,因为它有一个明确的内存地址,可以被取地址运算符 & 取出,存储在指针变量 pA 中。
1.2 rvalue
rvalue 是没有明确内存地址的,仅用于表达式计算的中间结果。其计算结果是一个临时值。
应用程序可以读取 rvalue,但不能直接修改其值。此外,rvalue 不能出现在赋值操作符左边。
int a = 5, b = 3, c;
c = a + b; //a+b是一个rvalue
上面这段代码中,a+b 是一个 rvalue,其结果是计算得到的临时值,在计算 c=a+b 后被丢弃。
2. 使用lvalue 和 rvalue
2.1 给变量赋值
lvalue 可以在赋值操作符的左边,因此它们可以用于变量的赋值操作。
int a;
a = 5; //使用lvalue赋值
rvalue 可以在赋值操作符的右边,因此它们可以用于计算表达式的结果。
int a, b, c;
a = 2;
b = 3;
c = a + b; //使用rvalue计算a+b的结果,并将结果赋值给c
2.2 函数参数
在函数调用中,参数可以是 lvalue 或 rvalue。
//参数a是lvalue,参数6是rvalue
void foo(int a, int b){
//...
}
int x = 5;
foo(x, 6);
在函数 foo() 中,参数 a 是 lvalue(因为它是一个有明确内存位置的变量),而参数 6 是 rvalue(因为它没有明确的内存位置)。
2.3 运算符和表达式
C语言中有一些运算符需要使用 lvalue 和 rvalue。例如:
++ 和 -- 运算符需要左值。
赋值操作符需要左值。
sizeof() 操作符可以接受 lvalue 或 rvalue。
三元运算符(?:)需要一个 rvalue 表达式和两个 lvalue 表达式。
int a = 5;
int b = 0;
b = ++a; //++a返回lvalue,可以被赋值给b
上面这段代码中,++a 是一个 lvalue,因此其结果可以被 b 赋值。
3. 总结
在 C 语言中,lvalue 和 rvalue 是基础概念,用于描述表达式中的不同元素。lvalue 是指向有明确内存位置的对象,其可以出现在赋值操作符的左边。rvalue 是临时表达式计算结果,其不能出现在赋值操作符的左边,其没有明确的内存位置。在 C 语言中,lvalue 和 rvalue 在赋值、函数参数、运算符和表达式等方面具有不同的使用规则。