【问题标题】:Are the literal and constant the same concept in C?C中的文字和常量是同一个概念吗?
【发布时间】:2012-07-31 03:48:48
【问题描述】:

C 中的字面量和常量是同一个概念吗? 它们在使用上有什么区别吗?

【问题讨论】:

    标签: c


    【解决方案1】:

    Literalsconstants 在 C 中是显着不同的东西。可以说 C 中的术语 literal 代表占据的未命名对象内存(文字通常是左值),而术语 constant 代表(可能命名)不一定占用内存的值(常量是右值)。

    “经典”C (C89/90) 只有一种文字:字符串文字。 C 中没有其他类型的字面量。C99 还引入了所谓的复合字面量

    同时,术语常量指的是显式值,例如12.5f0xA'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,这往往会导致混淆。

    (另见Shall I prefer constants over defines?

    【讨论】:

    • 我想知道谁误解了 OP,(s) 是指标准中使用的术语“常量”,还是 const-qualified 变量。但我不同意常量和文字是完全不同的东西,我看到 "String literal!"'c' 之间有一些相似之处。
    • @Daniel Fischer:OP 询问了 C 中的概念。所以我使用了语言规范中正式定义的术语。 const 限定的变量不是 C 中的常量。问题是关于常量的。不,字符串文字和字符常量之间没有相关的相似之处。说一匹马和一张桌子相似,只是因为它们都有四条腿,这并没有什么不同。没错,但无关紧要。
    • 我知道 const 限定的变量不是常量。我只是想知道OP是否这样做。其他答案将其解释为 const 限定变量,那么为什么 OP 不应该这样做呢?至于 no 相关的相似之处,我想这是一个解释问题。文字可以出现在静态变量的初始化程序中,否则只能出现常量。这并不多,但足以让我说完全/完全不同可能是夸大其词。
    • @Daniel Fischer:嗯,术语 literalconstant 在 C 语言中是非常严格定义的术语。在 OP 向我们提供任何迹象之前,我认为没有理由得出 OP 滥用这些术语的结论。即使 OP 滥用了这些术语,帮助 OP 正确使用它们也是正确的做法。没有任何理由就没有必要带来“解释”。文字和常量在 C 中确实是完全不同的东西:后者是对象(左值),而前者是值(右值)。这是一个巨大的差异。
    • 好吧,我不知道 OP 是否滥用了这些条款,我暂缓对此作出判断。但是这些术语经常被滥用以考虑这种可能性。我希望我们能就此达成一致;)(是的,它们是非常不同的野兽,只是 IMO 不是完全,YMMV。)
    【解决方案2】:

    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 * .53.40.4的小数部分在哪里,是截断了吗?
    • @ptr_user7813604:实际上数组下标必须是整数,所以我应该在示例中包含一个强制转换:&x[(int) (6.8 * .5)]。是的,将浮点数转换为整数时,会丢弃小数部分。
    【解决方案3】:

    不完全是。常量变量(与宏中定义的常量相反)是具有专用存储空间的实际变量,因此您可以获取它们的地址。您不能获取文字的地址。

    编辑:对不起大家,看来我弄错了。

    【讨论】:

    • 补充说明:static const变量的存储空间可以被编译器完全删除,所以你实际上并没有为使用常量变量付出“惩罚”。
    • “你不能获取文字的地址”。这是完全不正确的。您可以获取文字的地址。例如,字符串文字实际上会衰减到它自己的地址。您可以显式获取复合文字的地址。实际上,在 C 中 literal(与常量相对)是您 can 的地址。您不能获取常量的地址。
    • 并且添加到@AndreyT 所说的内容中,您也不能获取所有const 限定变量的地址,即当您使用存储类register 声明它们时。
    猜你喜欢
    • 2016-07-16
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-27
    • 1970-01-01
    • 2013-11-25
    相关资源
    最近更新 更多