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; }