一个表达式包括常量序列、标识符和操作符。程序中表达式的目的可能为了取得结果值,或赋值。
一个常量、字符串,或对象或函数的标识符均是一个表达式,复杂的表达式会使用括号,被称做主要表达式。
每个表达式都有一个类型,即为表达式结果值的类型,如果表达式不产生结果,它将具有void类型,下面是一些例子(假设变量a的类型为int, 变量z的类型为float_Complex)。
Table 5-1. Example expressions
Expression |
Type |
'/n' |
int |
a + 1 |
int |
a + 1.0 |
double |
a < 77.7 |
int |
“A sting literal.” |
char * |
abort() |
voied |
sqrt(2.0) |
double |
z / sqrt(2.0) |
double _Complex |
从上表可以看出,组合表达式会对操作数使用到操作符,且操作数可能为主要表达式或组合表达式,例如,在乘法中,你可以把一个函数调用当作因数,同样地,函数的参数也可以使用多个操作符,如下例:
2.0 * Sin(3.14159 * fAngleDegrees / 180.0)
在我们考虑操作符的细节前,本节提供了少许的原则,将会帮助你理解C中表达式是如何求值的,在分解组合表达式时,操作符的优先级尤为重要。但序列点和左值也同样要了解C语言如何工作。
左值为一个指明对象的表达式,最简单的例了是变量名,首字母L在术语中的意思是 left,因为一个左值指明一个对象,它可以出现在赋值操作符的左边。即:leftexpression = rightexpression.其他没有指明对象的表达式被称做右值,即,右值为一个表达式中,出现在赋值操作符右边,例如,常量和算术表达式。
一个左值通常可以理解为相应对象的地址,除过位域变量、或者使用register定义的变量。操作符产生一个左值包括[]和*.下面是一些例子。
Table 5-2. Pointer and array expressions may be lvalues
Expression |
Lvalue? |
array[1] |
Yes, an array element is an object with a location |
&array[1] |
No;the location of the object is not an object with a location |
ptr |
Yes;the pointer variable is an object with a loction |
*ptr |
Yes; what the pointer points to is also an object with a location |
ptr + 1 |
No; the addition yields a new address value, but not an object |
*ptr + 1 |
No; the addition yields a new arithmetic value, but not an object |
如果一个对象声明为常量,此时它将不能在表达式的左边使用,即使它是一个左值,如下例描述:
Int a = 1;
Const int b = 2, *ptr = &a;
b = 20; //Error: b is declared as const int.
*ptr = 10; // Error:ptr is declared as a pointer to const int.
在本例中,表达式a、b、ptr和*ptr均为左值,然而,b和*ptr为常量左值,因为ptr声明为指向const int的指针,你不能使用它来修改所指的对象,详细描述见第11章。
一个赋值语句的左操作数,像自增(++)和自减(--)操作符,不仅仅为一个左值,也为一个可修改的左值,可修改的左值不能使用const类型声明,且不为数组类型。如果一个可修改的左值指明一个结构或联合类型的对象,它的成员必须声明,直接或间接地,具有const限定类型。