在C语言中,字面值和常量是相同的概念吗?它们在使用中有什么区别吗?
字面值(literals)和常量(constants)在C语言中有着明显的区别。可以说,C语言中的字面值代表未命名占用内存的对象(通常是左值),而常量则代表不一定占用内存的(可能被命名的)值(常量是右值)。
C语言中的“经典”版本(C89/90)只有一种字面值:字符串字面值。在那个版本的C语言中没有其他类型的字面值。C99引入了所谓的复合字面值。
与此同时,术语常量指代显式的值,如1
、2.5f
、0xA
和's'
。此外,在C语言中,枚举成员也被认为是常量。
再次提醒,由于C语言中的字面值是左值,因此您可以获取并使用它们的地址。
const char *s = "Hello";
char (*p)[6] = &"World";
int (*a)[4] = &(int []) { 1, 2, 3, 4 };
因为常量是右值,所以你不能取它们的地址。
使用const
关键字声明的对象在C语言术语中不被视为常量。它们不能用于需要常量值的地方(比如case标签、位域宽度或全局、静态变量初始化)。
P.S. 注意,在C中相关的术语与C++有很大不同。在C++中,术语字面量实际上涵盖了大部分C中所知的常量。而在C++中,const
对象可以形成常量表达式。人们有时试图将C++术语强加于C之上,这经常导致混淆。
(另请参见我应该优先选择常量还是#define?)
"abc" "def"
变成"abcdef"
),附加了零字节,并使用结果初始化具有静态存储期的数组。因此,字符串字面量会导致对象。x
是一个静态数组,如static int x[8];
所声明的那样,则&x[(int) (6.8 * .5)]
是一个常数表达式:它是x的第3个元素的地址。(您很少使用浮点数索引数组,但我在示例中包括它是为了显示允许作为常数表达式的一部分。)int i; int *p = &i; const int *q = p;
中,q是指向const-int的指针,但i不是一个const对象,p是指向相同int的指针,尽管它是指向int而不是const。)6.8 * .5
等于 3.4
,小数部分为 0.4
,它被截断了吗? - Kindred&x[(int) (6.8 * .5)]
。是的,在将浮点数转换为整数时,小数部分会被舍去。 - Eric Postpischil不完全正确。常量变量(与宏定义的常量相对)是具有专用存储空间的实际变量,因此您可以获取它们的地址。您无法获取文字的地址。
编辑:对不起大家,看来我错了。
static const
变量的存储空间,因此使用常量变量实际上不会付出任何“惩罚”。 - Dietrich Eppconst
限定变量的地址,尤其是当你用存储类register
声明它们时。 - Jens Gustedt