c语言14:字符指针
在 C 语言中,字符指针(char*) 是处理字符串的核心工具之一。
它不仅能灵活指向单个字符,还能高效操作字符串常量。今天,我们就从基础用法到深层原理,全面探究字符指针的奥秘。
一、字符指针的基础:指向单个字符
字符指针最朴素的用法,是指向单个字符变量,通过指针间接访问或修改字符的值。
看这段代码:
#include <stdio.h>int main()
{char ch = 'w'; // 定义字符变量ch,值为'w'char *pc = &ch; // 字符指针pc指向ch的地址*pc = 'W'; // 通过解引用修改ch的值printf("ch = %c\n", ch); // 输出:ch = Wreturn 0;
}
关键逻辑:
char *pc
声明了一个字符指针变量pc
。&ch
获取字符变量ch
的内存地址,并赋值给pc
,此时pc
就 “指向” 了ch
。*pc
是解引用操作,表示 “访问pc
指向地址的内容”,因此*pc = 'W'
等价于直接修改ch
的值。
二、字符指针指向字符串常量:“地址” 而非 “内容”
字符指针更常见的场景,是指向字符串常量。很多初学者会误解 “把整个字符串存到指针里”,但本质是:指针存储的是字符串首字符的地址。
看这个例子:
#include <stdio.h>int main()
{const char* pstr = "hello bit."; // 字符指针pstr指向字符串首字符'h'的地址printf("%s\n", pstr); // 输出:hello bit.return 0;
}
深层理解:
"hello bit."
是字符串常量,C/C++ 会将其存储在只读数据区(防止程序意外修改常量内容)。const char* pstr
中的const
表示 “指针指向的内容是常量”—— 即不能通过pstr
修改字符串(比如*pstr = 'H'
会触发编译错误)。pstr
本身只存了首字符'h'
的内存地址,而非整个字符串的内容。printf("%s", pstr)
能打印完整字符串,是因为 C 语言约定:字符串以'\0'
(空字符)结尾,printf
会从首地址开始,直到遇到'\0'
才停止。
三、字符数组 vs 字符指针:内存模型的本质区别
为了彻底弄清字符指针与字符串的关系,我们对比字符数组和指向常量字符串的字符指针—— 这也是面试高频考点。
看这段经典代码:
#include <stdio.h>int main()
{// 场景1:字符数组char str1[] = "hello bit.";char str2[] = "hello bit.";// 场景2:指向常量字符串的字符指针const char *str3 = "hello bit.";const char *str4 = "hello bit.";// 比较str1和str2if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");// 比较str3和str4if (str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}运行结果:
str1 and str2 are not same
str3 and str4 are same
深度分析:
1. 字符数组 str1
和 str2
char str1[] = "hello bit.";
:程序会在栈内存中为str1
分配一块空间,然后把字符串"hello bit."
的内容拷贝到这块空间里。str2
同理:也是在栈上单独分配一块新内存,再拷贝字符串内容。- 因此,
str1
和str2
是两块完全独立的内存(地址不同),所以str1 == str2
为假(==
比较的是地址,而非内容)。
2. 字符指针 str3
和 str4
"hello bit."
是常量字符串,存储在只读数据区。编译器为了优化内存,会让多个指针共享同一个常量字符串的内存(只要字符串内容相同)。str3
和str4
都存储了这个常量字符串首字符'h'
的地址,因此str3
和str4
指向的是同一块内存,所以str3 == str4
为真。
四、字符指针的实用场景
除了基础用法,字符指针在实际开发中还有诸多妙用:
1. 函数参数传递字符串(高效性)
通过字符指针传递字符串,无需拷贝整个字符串(只传地址),效率更高:
#include <stdio.h>// 打印字符串的函数(接收字符指针)
void printString(const char *str)
{printf("String: %s\n", str);
}int main()
{const char *msg = "Hello, Function!";printString(msg); // 传递的是“地址”,而非拷贝整个字符串return 0;
}
2. 动态分配字符串(灵活性)
结合 malloc
动态分配内存,可灵活控制字符串长度:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main()
{// 动态分配能存10个字符的空间(包含结束符'\0')char *dynamicStr = (char *)malloc(10 * sizeof(char));if (dynamicStr != NULL) // 检查内存是否分配成功{ strcpy(dynamicStr, "Dynamic"); // 拷贝字符串到动态内存printf("Dynamic String: %s\n", dynamicStr);free(dynamicStr); // 用完后释放内存,避免泄漏}return 0;
}
五、总结
字符指针是 C 语言操作字符串的核心工具,核心要把握三点:
- 字符指针既可以指向单个字符,也可以指向字符串常量的首地址。
- 字符串常量存储在只读数据区,相同的常量字符串可能被编译器优化为 “共享内存”。
- 字符数组是 “存储字符串内容的内存块”,而字符指针是 “指向字符串地址的工具”—— 二者在内存分配、比较逻辑上有本质区别。
掌握字符指针,不仅能更高效地操作字符串,也是理解 C 语言内存模型的关键一步。