在 C++ 和 C 语言中,"literal"(字面值)和 "constant"(常量)的概念有显著差异,主要体现在术语定义、类型系统和语言特性上。以下是基于 C++14 和 C11 标准的详细对比分析:


​1. 术语定义差异​

​概念​

​C++ (ISO/IEC 14882:2014)​

​C (ISO/IEC 9899:2011)​

​Literal​

直接表示固定值的符号(token)
§2.13 [lex.literal]

无独立定义,属于常量的一种形式

​Constant​

广义常量(包括字面值、const变量等)

所有不可修改的值(包括字面值、枚举常量等)
§6.4.4

  • ​C++​​ 明确区分:

    • ​Literal​​:源代码中直接书写的固定值(如 42"text"

    • ​Constant​​:更广泛的概念,包括:

      • 字面值

      • const/constexpr变量

      • 枚举常量

      • 常量表达式结果

  • ​C​​ 中:

    • "Constant" 是统称,涵盖:

      • 字面值(Literals)

      • 枚举常量(Enumeration constants)

      • #define宏定义的常量

      • const限定的变量


​2. 类型系统差异​

​整数字面值​

​字面值​

​C++ 类型规则​

​C 类型规则​

42(十进制)

最小匹配类型:int→ long→ long long

同 C++

0xFF(十六进制)

最小匹配类型:int→ unsigned int→ long→ ...

无符号类型优先级更高​
(可能直接为 unsigned int

​关键区别​​:

C 对十六进制/八进制字面值的无符号性处理更激进(如 0xFFFF在 C 中默认为 unsigned int,而 C++ 可能为 int)。


​字符/字符串字面值​

​字面值​

​C++​

​C​

'A'

类型 char

类型 int(历史遗留)

"Hello"

类型 const char[6]

类型 char[6](​​可修改​​,但行为未定义)

​关键区别​​:

  • C 中字符串字面值可尝试修改(尽管是未定义行为):

    char* str = "hello";  // C 允许(但修改会UB)
    str[0] = 'H';         // 未定义行为!
  • C++ 禁止:

    const char* str = "hello"; // 必须加 const
    // str[0] = 'H';           // 编译错误

​3. 特有字面值类型​

​字面值类型​

​C++​

​C​

布尔字面值

true/false(类型 bool

无(C99 用 _Bool

指针字面值

nullptr(类型 std::nullptr_t

NULL(宏,通常是 (void*)0

用户自定义字面值

支持(如 42_km

不支持

原始字符串字面值

支持(R"(C:\Path)"

不支持


​4. 常量表达式能力​

​特性​

​C++​

​C​

编译时计算

constexpr函数和变量

仅支持简单常量表达式(C11 有 _Static_assert

数组大小

可用 constexpr变量

只能用字面值或枚举常量

模板元编程

依赖字面值和常量表达式

不支持

​示例​​:

// C++
constexpr int size = 10;
int arr[size];  // 合法

// C
#define SIZE 10  // 必须用宏或枚举
int arr[SIZE];   // 合法

​5. 标准中的具体位置​

  1. ​C++14​​:

    • §2.13 [lex.literal]:字面值定义和分类

    • §5.19 [expr.const]:常量表达式规则

    • §7.1.5 [dcl.constexpr]:constexpr说明符

  2. ​C11​​:

    • §6.4.4:常量(包括字面值)

    • §6.6:常量表达式

    • §6.7.2.1:枚举常量


​6. 代码行为对比示例​

示例 1:字符串修改
// C 语言(编译通过但运行时未定义行为)
#include <stdio.h>
int main() {
    char* s = "hello";
    s[0] = 'H';  // 未定义行为!
    printf("%s\n", s);
}
// C++(编译错误)
int main() {
    const char* s = "hello";
    // s[0] = 'H';  // 错误:尝试修改常量
}
示例 2:布尔类型
// C99(需要stdbool.h)
#include <stdbool.h>
bool flag = true;  // 实际是宏:#define true 1
// C++
bool flag = true;  // 原生布尔类型
示例 3:空指针
// C
int* ptr = NULL;  // #define NULL ((void*)0)
// C++
int* ptr = nullptr;  // 类型安全的空指针

​总结:核心差异​

​维度​

​C++ Literal​

​C Constant​

​术语定位​

独立概念(直接值表示)

"常量"的子集

​类型安全​

更强(如字符串只读、nullptr类型安全)

较弱(字符串可修改、NULL无类型)

​扩展性​

支持用户自定义字面值

不支持

​布尔/空指针​

原生支持 true/false和 nullptr

通过宏模拟

​常量表达式​

强大的 constexpr机制

仅基础编译时计算

​字符字面值​

类型 char

类型 int(历史原因)

理解这些差异对编写跨语言代码至关重要,尤其在涉及类型转换、内存操作和编译时计算时。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐