Skip to content

C 常量

C 语言常量与字面量 (Constants and Literals)

Section titled “C 语言常量与字面量 (Constants and Literals)”

在 C 语言中,术语 常量 (constant) 可以指代两个相关的概念:

  • 字面量 (Literals): 这些是直接写在源代码中的固定值,例如 123, 3.14, ‘A’, 或 “Hello”。它们的类型根据格式推断。
  • 常量变量 (Constant Variables): 这些是使用 const 关键字声明的变量,其值在初始化后不能修改。

字面量代表程序执行期间不会改变的值。它们可以是各种基本数据类型。

整型字面量代表整数。它们可以用不同的进制指定:

  • 十进制 (Decimal): 没有前缀(例如,123, -45)。
  • 八进制 (Octal): 前缀 0(例如,077 表示十进制的 63)。只使用数字 0-7。
  • 十六进制 (Hexadecimal): 前缀 0x 或 0X(例如,0xFF 表示十进制的 255,0x1a 表示十进制的 26)。使用数字 0-9、a-f、A-F。
  • 二进制 (Binary)(C23 标准): 前缀 0b 或 0B(例如,0b1011 表示十进制的 11)。注意:请检查编译器对 C23 特性的支持。

整型字面量可以带后缀 (suffixes) 来显式指定其类型:

  • u 或 U 表示 unsigned (无符号整型)。
  • l 或 L 表示 long (长整型)。
  • ll 或 LL 表示 long long (长长整型)(C99 及更高版本)。

后缀可以组合使用(例如,ul, ULL, Lu)。顺序不重要,大小写会被忽略。

整型字面量示例:

212 // int (十进制)
215u // unsigned int (无符号整型)
0xFeeL // long int (十六进制)
076 // int (八进制)
456ULL // unsigned long long (C99, 无符号长长整型)
0b101010ul // unsigned long (C23, 无符号长整型, 二进制)
// 常见错误:
// 078 // 非法:8 不是八进制数字
// 0xFG // 非法:G 不是十六进制数字
// 32UU // 非法:不能重复同类型的后缀 (U)

浮点型字面量 (Floating-Point Literals)

Section titled “浮点型字面量 (Floating-Point Literals)”

浮点型字面量代表实数(带小数部分 (fractional part) 的数字)。它们可以写成:

  • 十进制形式 (Decimal form): 必须包含小数点、指数 (exponent) 或两者都有(例如,3.14159, 123., .456, 1e-5)。
  • 指数形式 (Exponential form): 使用 e 或 E 后跟一个带符号的整型指数(例如,314159E-5L 表示 314159 * 10-5)。

默认情况下,浮点型字面量的类型是 double (双精度浮点型)。后缀可以指定其他浮点类型:

  • f 或 F 表示 float (单精度浮点型)。
  • l 或 L 表示 long double (长双精度浮点型)。

浮点型字面量示例:

3.14159 // double (双精度)
3.14f // float (单精度)
123.456L // long double (长双精度)
1.23e10 // double (1.23 * 10^10)
-5.E-2 // double (-0.05)
.001F // float (单精度)
// 常见错误:
// 510E // 非法:指数不完整
// 210f // 非法:浮点字面量需要小数点或指数
// .e55 // 非法:指数前缺少整数或小数部分

字符常量代表一个用单引号 (single quotes)(’ ‘)括起来的单个字符。在 C 语言中,其类型是 int (整型)。

示例:‘a’, ’%’, ‘7’。

特殊字符可以使用转义序列 (escape sequences) 表示,它们以反斜杠 (backslash)(</code>)开头:

转义序列含义
\n换行 (Newline)
\t水平制表符 (Horizontal tab)
\a响铃 (Alert/bell)
\b退格 (Backspace)
\r回车 (Carriage return)
\f换页 (Form feed)
\v垂直制表符 (Vertical tab)
\反斜杠字符 (\)
‘单引号字符 (')
“双引号字符 (")
?问号字符 (?)(用于避免三字符组 (trigraphs),现已基本弃用)
\ooo由八进制值 (octal value) 表示的字符(一到三位数字)
\xhh…由十六进制值 (hexadecimal value) 表示的字符(一位或多位数字)

使用转义序列的示例:

#include <stdio.h>
int main(void) {
printf("First line.\nSecond line with\ttab.\nBell sound:\a\n");
printf("Display single quote: \' and double quote: \"\n");
printf("Character with octal 77: %c\n", '\77'); // 八进制 77 是十进制 63,ASCII 码 '?'
printf("Character with hex 41: %c\n", '\x41'); // 十六进制 41 是十进制 65,ASCII 码 'A'
return 0;
}

输出(可能因终端而略有不同):

First line.
Second line with tab.
Bell sound:
Display single quote: ' and double quote: "
Character with octal 77: ?
Character with hex 41: A

字符串字面量是用双引号 (double quotes)(” “)括起来的字符序列。它表示一个字符数组 (array of characters),自动以空字符 (null character)(‘\0’)结尾。

示例:“Hello, world!\n”。这个字面量创建一个包含 14 个字符和一个最终的 ‘\0’ 的数组。

字符串字面量可以像字符常量一样包含转义序列。

相邻字符串字面量 (Adjacent string literals) 会被编译器自动连接 (concatenated) 成一个字符串字面量。这对于将长字符串分成多行书写很有用:

// 这三个定义创建了相同的字符串:
const char* str1 = "A long string literal.";
const char* str2 = "A long "
"string literal.";
const char* str3 = "A" " long" " string" " literal.";

在 C 语言中有两种主要方式来定义命名常量:

  1. 使用 #define 预处理器指令 (preprocessor directive)。
  2. 使用 const 关键字。

#define 创建一个宏 (macro)。预处理器 (preprocessor) 在编译开始前,会将每个标识符的出现替换为指定的值。

语法:#define IDENTIFIER value

示例:

#include <stdio.h>
#define PI 3.14159
#define GREETING "Hello"
#define NEWLINE '\n'
int main(void) {
double radius = 5.0;
double circumference = 2 * PI * radius;
printf("%s, the circumference is: %.2f%c", GREETING, circumference, NEWLINE);
return 0;
}

输出:

Hello, the circumference is: 31.42

优点: 定义常量不使用内存(简单的文本替换 (text replacement))。可以定义宏函数 (macro functions)(尽管通常有更好的替代方案)。

缺点: 编译器不进行类型检查 (Type checking)。如果将复杂表达式用作值,可能导致意外行为(请使用括号!)。不像变量那样受到调试器 (debuggers) 的支持。

const 关键字修饰变量声明 (qualifies a variable declaration),表明其值在初始化后不能更改。这些通常被称为“常量变量 (constant variables)”。

语法:const type variable_name = value;

示例:

#include <stdio.h>
int main(void) {
const int MAX_USERS = 100;
const double GRAVITY = 9.81;
const char TAB_CHAR = '\t';
printf("Max users: %d%cGravity: %.2f\n", MAX_USERS, TAB_CHAR, GRAVITY);
// Error: Cannot assign to read-only variable 'MAX_USERS'
// MAX_USERS = 150;
return 0;
}

输出:

Max users: 100 Gravity: 9.81

优点: 类型安全(编译器检查类型)。遵循作用域规则 (scope rules)。可以被调试器 (debuggers) 查看。通常优先于 #define 用于定义带类型的常量。

注意: 按照惯例,#define 宏的标识符通常全大写(例如,MAX_USERS)。虽然这个约定有时也用于 const 变量,但并不普遍;标准的变量命名约定 (standard variable naming conventions)(例如,camelCase (驼峰命名法) 或 snake_case (蛇形命名法))对于 const 变量也很常见。