在C语言中,字符串是必须以空字符\0结尾的特殊字符数组,而普通字符数组不一定包含\0;字符串字面量(如"Hello")存储在只读区不可修改,但字符数组(如char arr[] = "Hello")在栈上可修改;使用时必须确保字符串以\0结尾,否则标准库函数(如strlen)会因未定义行为导致错误。

在C语言中,字符数组和字符串经常被混淆,但它们有重要区别。

基本定义

  • 字符数组:是一个固定大小的数组,元素类型是char。可以存储字符序列,但不一定'\0'结尾。

    char arr[5] = {'H', 'e', 'l', 'l', 'o'}; // 不是字符串(无'\0')
    
  • 字符串:在C中,字符串是以'\0'(空字符)结尾的字符数组。通常用双引号" "定义,编译器会自动添加'\0'

    char str[] = "Hello"; // 等价于 {'H', 'e', 'l', 'l', 'o', '\0'}
    

关键区别

特性字符数组字符串
结尾标志不一定以'\0'结尾必须'\0'结尾
内存大小仅存储字符,大小等于元素个数大小 = 字符个数 + 1(用于'\0'
可变性可修改(栈/堆分配)字符串字面量不可修改(常量区)
初始化方式逐个字符初始化用字符串常量初始化(自动添加'\0'
存储位置栈/堆栈/堆/常量区(字符串字面量)

重要示例

// 字符数组(不是字符串,没有'\0')
char arr1[5] = {'H', 'e', 'l', 'l', 'o'};

// 字符串(有'\0'结尾)
char arr2[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char str1[] = "Hello"; // 自动添加'\0'

// 字符串字面量(常量区,不可修改)
char *str2 = "Hello";
// str2[0] = 'h'; // 错误!运行时崩溃

常见问题

  1. 缺少\0导致问题

    char arr[3] = {'a', 'b', 'c'};
    printf("%s", arr); // 错误!没有'\0',可能打印乱码
    
  2. 字符串字面量不可修改

    char *s = "abc";
    s[0] = 'x'; // 非法!运行时错误
    
  3. 缓冲区溢出

    char arr[5] = "Hello"; // 错误!需要6字节(包括'\0')
    

字符串长度

  • sizeof(arr):包括\0,所以结果比实际字符数多1
  • strlen(arr):不包括\0,直到遇到\0停止
char str[] = "Hello";
printf("sizeof(str) = %zu\n", sizeof(str)); // 输出6
printf("strlen(str) = %zu\n", strlen(str));  // 输出5

正确使用方法

  1. 如果需要修改字符串

    char str[] = "Hello"; // 栈分配,可修改
    str[0] = 'H'; // 合法
    
  2. 如果需要只读字符串

    const char *s = "Hello"; // 指向字符串字面量,只读
    
  3. 处理字符串时必须确保有\0

    char arr[10];
    for(int i = 0; i < 5; i++) {
        arr[i] = 'a' + i;
    }
    arr[5] = '\0'; // 必须添加结束符
    

总结

  • C语言中没有专门的字符串类型,字符串是通过字符数组实现的。
  • 字符串是字符数组的特殊形式:字符数组末尾添加'\0'
  • 字符串字面量(如"Hello")是存储在常量区的只读数据。
  • 字符数组(如char arr[] = "Hello")在栈上,可修改。
  • 始终确保字符串以\0结尾,否则标准库函数(如strlen, printf)会出错。

记住:字符串 = 字符数组 + '\0'。这是理解C语言字符串处理的关键。