C 常量
C 语言常量与字面量 (Constants and Literals)
Section titled “C 语言常量与字面量 (Constants and Literals)”在 C 语言中,术语 常量 (constant) 可以指代两个相关的概念:
- 字面量 (Literals): 这些是直接写在源代码中的固定值,例如
123,3.14,‘A’, 或“Hello”。它们的类型根据格式推断。 - 常量变量 (Constant Variables): 这些是使用
const关键字声明的变量,其值在初始化后不能修改。
字面量代表程序执行期间不会改变的值。它们可以是各种基本数据类型。
整型字面量 (Integer Literals)
Section titled “整型字面量 (Integer Literals)”整型字面量代表整数。它们可以用不同的进制指定:
- 十进制 (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 // 非法:指数前缺少整数或小数部分字符常量 (Character Constants)
Section titled “字符常量 (Character Constants)”字符常量代表一个用单引号 (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
字符串字面量 (String Literals)
Section titled “字符串字面量 (String Literals)”
字符串字面量是用双引号 (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.";
定义常量 (Defining Constants)
Section titled “定义常量 (Defining Constants)”
在 C 语言中有两种主要方式来定义命名常量:
- 使用
#define 预处理器指令 (preprocessor directive)。
- 使用
const 关键字。
#define 预处理器 (Preprocessor)
Section titled “#define 预处理器 (Preprocessor)”
#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 关键字
Section titled “const 关键字”
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 变量也很常见。