在C语言里,字符串本质上是以空字符结尾的连续字符序列。用指针操作字符串,就是直接通过地址运算来访问和修改这些字符,而不依赖数组下标语法。这种方式更贴近机器底层,也能让代码更紧凑。

字符数组与指针的基础差异
当我们声明一个字符数组时,编译器会在栈上分配一段固定长度的内存,数组名在大多数表达式中会退化为指向首元素的常量指针。而用指针变量指向字符串字面量时,指针本身在栈上,它指向的字符通常位于只读数据段。
下面两段代码完成同样的事,但内存布局不同。数组版本可随意修改内容,指针版本指向字面量则不可写。理解这点对后续操作至关重要,否则容易触发段错误。
#include <stdio.h>
int main() {
char arr[20] = "hello";
char *ptr = "hello";
arr[0] = 'H'; // 合法,栈上内存可写
// ptr[0] = 'H'; // 未定义行为,字面量区只读
printf("%sn", arr);
printf("%sn", ptr);
return 0;
}
用指针实现字符串拷贝
指针拷贝字符串的核心是利用解引用和自增运算,逐个字符移动,直到遇到结束符。相比数组下标,指针版本少了一个显式的索引变量,逻辑更直白。
下面给出一个自定义的指针版字符串拷贝函数。注意目标空间必须足够大,且源串须以空字符结尾,否则会越界读。函数返回目标首地址,方便链式调用。
#include <stdio.h>
char *my_strcpy(char *dest, const char *src) {
char *start = dest;
while (*src != ' ') {
*dest = *src;
dest++;
src++;
}
*dest = ' ';
return start;
}
int main() {
char buf[20];
my_strcpy(buf, "pointer copy");
printf("%sn", buf);
return 0;
}
若改用字符数组下标写法,循环体内要用索引访问,代码稍显啰嗦,但可读性对新手更友好。二者生成的机器指令在开启优化后往往相近。
指针拼接与遍历统计
拼接字符串时,指针先移动到目标串的末尾,再复用拷贝逻辑。这种方式避免了每次从头计算长度,效率更高。以下示例用指针找到结尾并追加。
我们还演示了用指针遍历统计元音字母个数,展示指针在扫描场景下的简洁性。每个字符通过解引用取出,指针前进一字节即可。
#include <stdio.h>
void my_strcat(char *dest, const char *src) {
while (*dest != ' ') dest++; // 移到末尾
while (*src != ' ') {
*dest = *src;
dest++;
src++;
}
*dest = ' ';
}
int count_vowel(const char *s) {
int n = 0;
while (*s) {
if (*s=='a'||*s=='e'||*s=='i'||*s=='o'||*s=='u') n++;
s++;
}
return n;
}
int main() {
char msg[50] = "hello";
my_strcat(msg, " world");
printf("%sn", msg);
printf("vowels: %dn", count_vowel(msg));
return 0;
}
对比总结与避坑要点
从处理方式看,字符数组强调“容器”概念,长度在编译期部分确定;指针强调“游标”概念,更灵活但也更易悬空。函数传参时,数组会退化为指针,因此函数内无法用sizeof获知原数组大小,必须额外传长度。
常见陷阱包括:指针指向字面量后尝试修改、目标缓冲区过小导致溢出、未初始化指针就解引用。建议涉及写操作时优先用数组明确空间,纯读取遍历可用指针提升表达力。
| 维度 | 字符数组 | 指针操作 |
|---|---|---|
| 内存位置 | 栈或全局区可写 | 指向字面量时只读 |
| 可修改性 | 内容可改 | 取决于指向对象 |
| 传参表现 | 退化为指针失尺寸 | 本身即为地址 |
| 典型用途 | 缓冲与构造 | 扫描与只读访问 |
C_languagestring_pointerchar_array修改时间:2026-08-01 22:33:32