【发布时间】:2012-07-31 03:48:48
【问题描述】:
C 中的字面量和常量是同一个概念吗? 它们在使用上有什么区别吗?
【问题讨论】:
标签: c
C 中的字面量和常量是同一个概念吗? 它们在使用上有什么区别吗?
【问题讨论】:
标签: c
Literals 和 constants 在 C 中是显着不同的东西。可以说 C 中的术语 literal 代表占据的未命名对象内存(文字通常是左值),而术语 constant 代表(可能命名)不一定占用内存的值(常量是右值)。
“经典”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 术语中不被视为常量。它们不能用于需要常量值的地方(例如大小写标签、位域宽度或全局、静态变量初始化)。
附:请注意,C 中的相关术语与 C++ 中的术语有很大不同。在 C++ 中,术语 literal 实际上涵盖了 C 中称为 constants 的大部分内容。而在 C++ 中,const 对象可以形成常量表达式。人们有时试图将 C++ 术语强加于 C,这往往会导致混淆。
【讨论】:
const-qualified 变量。但我不同意常量和文字是完全不同的东西,我看到 "String literal!" 和 'c' 之间有一些相似之处。
C 标准(特别是 ISO/IEC 9899,第二版,1999-12-01)本身并没有定义“literal”,所以这不是 C 的特定概念。我发现“literal”的三种用法,如下所述。
首先,字符串文字(或正式语法中的“字符串文字”)是引号内的字符序列,可选地以“L”作为前缀(这使其成为宽字符串文字)。这无疑被称为文字,因为字符串中的每个字符都代表自己:源文本中的“b”导致字符串中的“b”。 (相比之下,源文本中的字符“34”是一个数字,而不是字符串,在程序中会产生值 34,而不是字符“3”和“4”。)这些文字的语义定义在6.4.5 第 4 和 5 段。本质上,相邻的字面量是连接在一起的("abc" "def" 变成了"abcdef"),附加了一个零字节,结果用于初始化一个静态存储持续时间的数组。所以字符串字面量会产生一个对象。
其次,复合文字是一种更复杂的构造,用于为结构创建值。 “复合文字”是一个不幸的名字,因为它根本不是文字。也就是说,文字源文本中的字符不一定完全代表它们自己。事实上,复合文字甚至不是常数。复合文字可以包含在运行时计算的表达式,包括函数调用!
第三,在 6.1 第 1 段中,标准指出“字面词和字符集成员”用粗体字表示。这种“字面”的使用是在描述标准本身,而不是在 C 语言中描述事物;表示标准中的“goto”表示C语言中的字符串“goto”。
除了字符串字面量,我不认为“字面量”是 C 语言中的一个特殊概念。
然而,“常数”是一个重要的概念。
首先,有一些简单的常量,例如“34”、“4.5f”和“'b'”。后者是字符常量;虽然是用字符写的,但它有一个整数值。常量包括整数常量(十进制、八进制和十六进制)、浮点常量(十进制和十六进制)、字符常量和枚举常量。枚举常量是在“枚举”结构中指定的名称。
其次,有常量表达式,在 6.6 中定义。常量表达式可以在翻译(编译时)而不是运行时进行评估,并且可以在常量可能存在的任何地方使用。 6.6 为常量表达式设置了一定的规则。例如,如果x 是一个静态数组,如static int x[8]; 所声明的,那么&x[(int) (6.8 * .5)] 是一个常量表达式:它是x 的元素3 的地址。 (您很少使用浮点数来索引数组,但我将其包含在示例中以表明它可以作为常量表达式的一部分。)
关于“const”:该标准似乎没有专门将 const 限定的对象定义为常量。相反,它表示尝试通过具有非 const 限定类型的左值(例如取消引用的指针)修改使用 const 限定类型定义的对象,行为是未定义的。这意味着不需要 C 实现来强制 const 对象的恒定性。 (另外,请注意,有一个指向 const 的指针并不意味着指向的对象是 const,只是取消引用的指针不是可修改的左值。可能有一个指向同一对象的单独指针,它不是 const 限定的. 例如,在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的小数部分在哪里,是截断了吗?
&x[(int) (6.8 * .5)]。是的,将浮点数转换为整数时,会丢弃小数部分。
不完全是。常量变量(与宏中定义的常量相反)是具有专用存储空间的实际变量,因此您可以获取它们的地址。您不能获取文字的地址。
编辑:对不起大家,看来我弄错了。
【讨论】:
static const变量的存储空间可以被编译器完全删除,所以你实际上并没有为使用常量变量付出“惩罚”。
const 限定变量的地址,即当您使用存储类register 声明它们时。