1、基本区别
char *s
是一个指针,指向一个字符数组或字符串的首地址。char s[]
是一个字符数组,存储字符串或一系列字符。
#include <stdio.h>
int main() {
// char *s 指向一个常量字符串
char *s1 = "hello";
// char s[] 是一个字符数组
char s2[] = "world";
// 修改字符串内容
s2[0] = 'W'; // 可以修改
// s1[0] = 'H'; // 错误,不能修改常量字符串
// 修改指针指向
s1 = "hello, world"; // 可以修改指针指向
// 输出结果
printf("%s\n", s1); // 输出 hello, world
printf("%s\n", s2); // 输出 World
return 0;
}
2、内存布局的区别
1)char *s(指针)
"Hello"
是字符串字面量,存储在只读内存(只读数据段)中。s
是一个指针变量,存储在栈上,指向字符串 "Hello"
的首地址。由于字符串字面量存储在只读内存中,试图修改 *s
指向的内容会导致段错误(segmentation fault)。
#include <stdio.h>
int main() {
char *s = "Hello";
printf("%s\n", s);
// 错误:试图修改只读内存中的字符串会导致段错误
// s[0] = 'h';
return 0;
}
2)char s[](字符数组)
char s[] = "Hello"
是一个字符数组,存储在栈上,并且数组中的内容可以修改。由于字符串存储在栈上,因此可以修改数组中的字符。
#include <stdio.h>
int main() {
char s[] = "Hello";
s[0] = 'h'; // 这是合法的,因为数组 s 在栈上,可以修改
printf("%s\n", s); // 输出 "hello"
return 0;
}
3、初始化的区别
char *s
只能将指针初始化为字符串字面量或现有数组的地址。char s[]
可以在声明时直接赋初值。
#include <stdio.h>
int main() {
// s指向一个字符串常量
char *s1 = "Hello, World!";
// 输出: Hello, World!
printf("%s\n", s1);
// s是一个字符数组,存储字符串
char s2[] = "Hello, World!";
// 输出: Hello, World!
printf("%s\n", s2);
return 0;
}
4、修改的区别
char *s
不能修改指向的字符串内容。char s[]
可以修改数组中的字符。如果 s
指向的是一个字符串常量,那么尝试修改这个字符串会导致未定义行为。如果 s
指向的是动态分配的内存,那么可以修改。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
// 使用 char *s
char *s1 = "Hello";
// s1[0] = 'M'; // 未定义行为,注释掉以避免错误
printf("s1: %s\n", s1);
s1 = malloc(10 * sizeof(char));
strcpy(s1, "Hello");
s1[0] = 'M'; // 合法
printf("s1 after modification: %s\n", s1);
free(s1);
// 使用 char s[]
char s2[] = "Hello";
s2[0] = 'M'; // 合法
printf("s2 after modification: %s\n", s2);
return 0;
}
5、传递给函数的区别
函数参数中,char *
和 char []
的效果是相同的。字符数组会退化为指针传递。
#include <stdio.h>
void printString(char *str) {
printf("%s\n", str);
}
int main() {
char s1[] = "Hello";
char *s2 = "World";
printString(s1); // 数组退化为指针
printString(s2); // 直接传递指针
return 0;
}