C语言中,char *s 和 char s[] 虽然都用于表示字符串,但它们在本质上有着显著的不同,主要体现在内存分配、可修改性以及使用场景等方面。char *s 是一个指向字符的指针,可以指向不同的字符串,但指向的字符串常量内容不可修改。char s[] 是一个字符数组,内容可以被修改,但在编译时大小固定。

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