const关键字的核心作用const char的两种主要用法- *`const char
vs.char constvs.char const`(重点和难点)** const char*与char*的主要区别- 实际应用场景和最佳实践
- 常见误区
const 关键字的核心作用
const 是 C 语言中的一个关键字,是 constant(常量) 的缩写,它的核心作用是 “承诺”。

(图片来源网络,侵删)
当一个变量被声明为 const 时,你就在向编译器和代码的阅读者做出一个承诺:这个变量的值在初始化之后,绝不会再被修改。
编译器会检查所有对这个变量的操作,一旦发现试图修改它的代码,就会在编译阶段报错,这提供了一种强大的机制来防止代码被意外修改,从而提高代码的健壮性和可读性。
const int MAX_AGE = 100; // MAX_AGE = 101; // 错误!编译器会报错:assignment of read-only variable 'MAX_AGE'
const char 的两种主要用法
const char 本身不是一个完整的类型,它通常作为指针类型的一部分出现,主要有两种常见的组合:
a) const char * (指向字符常量的指针)
这是最常见、也最容易混淆的一种,它表示: “这是一个指针,它指向一个字符,而这个字符是常量,不能通过这个指针来修改。”

(图片来源网络,侵删)
关键点:
- *
const修饰的是 `` 指向的内容**,也就是指针所指向的内存地址中的值。 - 指针本身(存放地址的变量)是可以修改的,可以指向其他地方。
示例:
char str1[] = "hello";
char str2[] = "world";
const char *ptr = str1; // ptr 指向 str1 的第一个字符 'h'
// 1. 不能通过 ptr 修改指向的内容
// *ptr = 'H'; // 错误!编译器报错:assignment of read-only location '*ptr'
// 2. ptr 本身可以指向别处
ptr = str2; // 正确!ptr 指向 str2 的第一个字符 'w'
printf("%s\n", ptr); // 输出: world
// 3. 直接修改 str1 数组本身是允许的,因为 str1 数组本身不是 const
str1[0] = 'H'; // 正确
printf("%s\n", str1); // 输出: Hello
// ptr 仍然指向 str2,不受影响
b) char * const (指向字符的常量指针)
这种用法相对少见,它表示: “这是一个指针,它本身是常量,不能指向别处,但它指向的内容可以通过这个指针来修改。”
关键点:

(图片来源网络,侵删)
const修饰的是指针ptr本身,也就是存放地址的变量不能被修改。- 指针指向的内容(
*ptr)不是const,可以被修改。
示例:
char str1[] = "hello";
char str2[] = "world";
char * const ptr = str1; // ptr 是一个常量指针,初始化后不能再指向别处
// 1. 不能修改 ptr 本身(让它指向别处)
// ptr = str2; // 错误!编译器报错:assignment of read-only variable 'ptr'
// 2. 可以通过 ptr 修改它指向的内容
*ptr = 'H'; // 正确
printf("%s\n", ptr); // 输出: Hello
printf("%s\n", str1); // 输出: Hello (因为 ptr 指向 str1)
// 3. 直接修改 str1 数组本身也是允许的
str1[1] = 'a';
printf("%s\n", str1); // 输出: Hallo
const char* vs. char const* vs. char* const(重点和难点)
这是理解 const 和指针关系的关键,记住一个简单的规则:const 总是离它最近的那个东西是常量。
const char *ptr
- 解读:
const离 所以*ptr是常量。 - 含义:指向常量的指针,不能通过
ptr修改*ptr的值,但ptr可以指向别处。 - 等价于:
char const *ptr。
char const *ptr
- 解读:
const离 所以*ptr是常量。 - 含义:同上,指向常量的指针,这是 C++ 风格的写法,但在 C 中与
const char *ptr完全等价。 - 等价于:
const char *ptr。
char * const ptr
- 解读:
const离ptr所以ptr本身是常量。 - 含义:指针常量。
ptr不能指向别处,但可以通过ptr修改*ptr的值。
const char * const ptr (终极版)
- 解读:
const离*ptr是常量;const离ptrptr本身也是常量。 - 含义:指向常量的常量指针,既不能通过
ptr修改*ptr的值,也不能让ptr指向别处,指针和它指向的内容都是不可变的。
总结表格:
| 声明 | 含义 | 能否修改指针指向的内容? | 能否修改指针本身(指向别处)? |
|---|---|---|---|
const char *ptr |
指向字符常量的指针 | 否 | 是 |
char const *ptr |
指向字符常量的指针 | 否 | 是 |
char * const ptr |
指向字符的常量指针 | 是 | 否 |
const char * const ptr |
指向字符常量的常量指针 | 否 | 否 |
const char* 与 char* 的主要区别
| 特性 | char* (普通字符指针) |
const char* (指向常量的字符指针) |
|---|---|---|
| 可变性 | 指针和它指向的内容都可以被修改(前提是内存可写)。 | 指针可以修改,但不能通过这个指针修改它指向的内容。 |
| 安全性 | 较低,如果函数内部意外修改了传入的字符串,可能导致外部数据被破坏。 | 较高,当函数参数是 const char* 时,它向调用者承诺:我不会修改你的字符串,这是一种接口契约。 |
| 用途 | 通常用于需要创建和修改的场景,如字符数组。 | 通常用于读取和传递的场景,如函数参数、从函数返回字符串字面量。 |
实际应用场景和最佳实践
函数参数(保护数据)
当你写一个函数,只需要读取字符串内容,而不需要修改它时,应该使用 const char* 作为参数类型。
// 好的做法
void print_message(const char *msg) {
// 函数内部可以保证不会修改 msg 指向的内容
printf("Message: %s\n", msg);
// msg[0] = 'X'; // 如果这里尝试修改,编译器会报错!
}
int main() {
char my_string[] = "Hello C";
print_message(my_string); // 安全地传递
const char *literal = "This is a literal";
print_message(literal); // 也可以安全地传递字符串字面量
return 0;
}
如果不使用 const,函数内部就有可能意外修改调用方的数据,造成难以发现的 bug。
从函数返回字符串(返回字面量)
当你从函数中返回一个固定的、不需要修改的字符串时,返回 const char* 是最佳实践。
const char* get_status_message(int code) {
switch (code) {
case 200: return "OK";
case 404: return "Not Found";
case 500: return "Internal Server Error";
default: return "Unknown Error";
}
}
int main() {
printf("Status: %s\n", get_status_message(404)); // 输出: Status: Not Found
// const char *msg = get_status_message(200);
// msg[0] = 'O'; // 错误!不能修改字符串字面量
return 0;
}
这里返回的是程序只读数据区(.rodata section)中的字符串字面量,绝对不能被修改,使用 const char* 明确地告诉了调用者这一点。
常见误区
-
*误区:`const char ` 指向的内存一定是不可修改的。**
- 真相:
const char *只是承诺不通过这个指针去修改,如果指针指向的是一个普通的、可写的字符数组(如char str[] = "hello";),那么你可以通过其他方式(比如直接使用数组名str)来修改它。const的约束只对指针本身有效。
- 真相:
-
误区:
const变量的值必须在编译时确定。- 真相:
const变量可以在运行时初始化,只要初始化后不再修改即可。int x; scanf("%d", &x); const int y = x; // 正确,y 在运行时被赋值,之后不能修改
- 真相:
-
误区:
const和#define宏定义常量完全一样。- 真相:它们有本质区别。
#define是在预处理阶段进行简单的文本替换,没有类型安全,只是宏。const是在编译阶段处理的,它是一个有类型的、带名字的变量,有自己的内存地址(如果需要),编译器会对其进行类型检查。
- 真相:它们有本质区别。
const char的核心是const,它承诺“不可变”。const char *是指向字符常量的指针,是最常用的形式,用于安全地传递和读取字符串。char * const是指针常量,较少使用,表示指针本身不可变。- 理解
const修饰的对象(是 还是变量名)是关键。 - 在 C 语言编程中,强烈推荐将不需要修改的指针参数声明为
const类型,这是一种良好的编程习惯,能极大地提升代码的安全性和可读性。
