C语言string与string有何区别?

99ANYc3cd6
预计阅读时长 19 分钟
位置: 首页 C语言 正文
  1. 核心概念:C 语言没有内置的 "string" 类型
  2. C 语言中的字符串是如何表示的?
  3. 最重要的字符串函数库:<string.h>
  4. C++ 中的 std::string (作为对比)
  5. 总结与最佳实践

核心概念:C 语言没有内置的 "string" 类型

这一点是理解 C 语言字符串的关键,与 C++、Java、Python 等现代语言不同,C 语言没有一个原生的、名为 string 的数据类型。

c语言string string
(图片来源网络,侵删)

你不能这样写:

// 错误!C 语言中没有 string 类型
string name = "Alice";

C 语言是如何处理文本(字符串)的呢?答案是:通过字符数组


C 语言中的字符串是如何表示的?

在 C 语言中,字符串被实现为一个以 空字符 ('\0') 结尾的字符数组。

  • 字符数组: 一系列连续的内存空间,每个空间存放一个 char 类型的字符。
  • 空字符 ('\0'): 这是一个特殊的字符,其 ASCII 码值为 0,它标志着字符串的结束,C 语言标准库中的所有字符串函数都依赖这个空字符来判断字符串的长度。

两种主要的字符串声明方式:

使用字符数组

c语言string string
(图片来源网络,侵删)
char str1[] = "Hello, World!";
// 等价于:
// char str1[] = {'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\0'};
  • 内存布局:
    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
    | H | e | l | l | o | , |   | W | o | r | l | d | ! | \0 |
    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  • 特点:
    • 编译器会自动计算字符个数并添加结尾的 '\0'
    • 数组的大小是固定的。sizeof(str1) 的值是 14(13个字符 + 1个 '\0')。
    • 这种方式声明的字符串是可修改的

使用字符指针

char *str2 = "Hello, World!";
  • 内存布局:

    • str2 是一个指针变量,它存储的是字符串字面量 "Hello, World!" 在内存中的首地址
    • 字符串字面量通常存储在程序的只读数据段
    • str2 本身是一个变量,可以指向其他地址,但它最初指向的内容是不可修改的
  • 特点:

    • str2 是一个指针,它指向字符串的第一个字符。
    • sizeof(str2) 的值通常不是字符串的长度,而是指针变量本身的大小(在 64 位系统上是 8 字节,在 32 位系统上是 4 字节)。
    • 警告:尝试修改 str2 指向的内容是未定义行为,通常会导致程序崩溃。
      str2[0] = 'M'; // 错误!可能导致段错误

最重要的字符串函数库:<string.h>

为了方便我们操作字符串,C 标准库提供了 <string.h> 头文件,里面包含了一系列非常有用的函数。

c语言string string
(图片来源网络,侵删)

下面是一些最常用的函数:

函数 描述 示例
strlen(s) 返回字符串 s长度(不包括结尾的 '\0')。 len = strlen("abc"); // len 的值是 3
strcpy(dest, src) 将字符串 src(源)复制dest(目标)中。目标空间必须足够大! strcpy(buffer, "Hello");
strcat(dest, src) 将字符串 src 连接dest 的末尾。目标空间必须足够大! strcat(buffer, " World!");
strcmp(s1, s2) 比较两个字符串,返回值:
- 0s1s2 相等
- < 0s1 小于 s2 (按字典序)
- > 0s1 大于 s2
if (strcmp(name, "admin") == 0) { ... }
strncpy(dest, src, n) 安全版本的 strcpy,最多复制 n 个字符。注意:srcn 短,dest 不会自动添加 '\0' strncpy(buffer, "Hi", 5);
strncat(dest, src, n) 安全版本的 strcat,最多连接 n 个字符。 strncat(buffer, "!", 1);
strchr(s, c) 在字符串 s 中查找字符 c,返回指向该字符的指针,如果找不到则返回 NULL p = strchr("hello", 'l'); // p 指向第二个 'l'
strstr(s1, s2) 在字符串 s1 中查找子串 s2,返回指向子串首字符的指针,如果找不到则返回 NULL p = strstr("hello world", "world");

示例代码:

#include <stdio.h>
#include <string.h> // 必须包含这个头文件
int main() {
    char str1[50] = "Hello"; // 确保空间足够大
    char str2[] = ", C String!";
    char str3[50];
    // 1. strlen
    printf("Length of str1: %zu\n", strlen(str1)); // 使用 %zu 打印 size_t 类型
    // 2. strcpy
    strcpy(str3, str1); // 将 str1 复制到 str3
    printf("After strcpy, str3 is: %s\n", str3);
    // 3. strcat
    strcat(str3, str2); // 将 str2 连接到 str3
    printf("After strcat, str3 is: %s\n", str3);
    // 4. strcmp
    if (strcmp(str1, "Hello") == 0) {
        printf("str1 is equal to 'Hello'\n");
    }
    // 5. strncpy (更安全)
    char dest[10];
    strncpy(dest, "This is a very long string", 9); // 只复制9个字符
    dest[9] = '\0'; // 手动添加结束符!非常重要!
    printf("After strncpy, dest is: %s\n", dest);
    return 0;
}

C++ 中的 std::string (作为对比)

很多人在学习 C 语言时,会听到 C++ 的 std::string,这常常造成混淆。

  • *C 语言 (`char`)**:

    • 本质: 一个指向字符的指针。
    • 管理: 手动管理内存,你需要自己分配足够的内存(malloc/new),并在使用后释放(free/delete),如果忘记 '\0',函数就会越界读取,导致严重错误(缓冲区溢出)。
    • 操作: 依赖 <string.h> 中的 C 风格函数,使用起来不够直观(如 strcpy(dest, src) 需要记住参数顺序)。
  • C++ (std::string):

    • 本质: 一个,封装了字符数组和相关的操作。

    • 管理: 自动管理内存,当你创建 std::string 对象时,它会自动分配内存;当对象生命周期结束时,析构函数会自动释放内存,你完全不用担心内存泄漏。

    • 操作: 提供了成员函数和操作符重载,使用起来非常直观和方便。

      #include <string>
      #include <iostream>
      int main() {
          std::string s1 = "Hello";
          std::string s2 = ", C++ String!";
          // 自动管理内存,无需担心大小
          std::string s3 = s1 + s2; // 使用 + 操作符连接,非常直观
          // 获取长度使用成员函数
          std::cout << "Length of s3: " << s3.length() << std::endl;
          // 访问和修改像普通数组一样安全
          s3[0] = 'M';
          std::cout << "s3 is now: " << s3 << std::endl;
          return 0;
      }

总结对比: | 特性 | C String (char*) | C++ std::string | | :--- | :--- | :--- | | 类型 | 指针 | 类对象 | | 内存管理 | 手动 (malloc, free) | 自动 (RAII) | | 安全性 | 低,容易出错(缓冲区溢出) | 高,边界检查更完善 | | 易用性 | 较低,函数式调用 | 高,面向对象,操作符重载 | | 性能 | 轻量级,直接操作内存 | 稍重,但有优化(如写时拷贝) |


总结与最佳实践

  1. 记住核心: C 语言中的 string 不是一种类型,而是以 '\0' 结尾的字符数组

  2. 两种声明:

    • char str[] = "...":用于定义可修改的字符串,数组大小固定。
    • char *str = "...":用于定义指向只读字符串字面量的指针。
  3. 使用 <string.h>: 所有字符串操作都应使用标准库函数,不要自己用循环实现,这样既安全又高效。

  4. 注意安全:

    • 使用 strcpystrcat 时,务必确保目标缓冲区足够大,否则会导致缓冲区溢出,这是严重的安全漏洞。
    • 优先使用更安全的 strncpystrncat,但要注意它们不会自动添加 '\0',你需要手动处理。
  5. 现代 C++ 的选择: 如果你在使用 C++,强烈推荐使用 std::string 来处理所有文本,它能为你解决绝大多数 C 风格字符串带来的麻烦,只有在需要与 C 语言库交互或进行底层性能优化时,才使用 const char*char*

希望这个详细的解释能帮助你彻底理解 C 语言中的 string

-- 展开阅读全文 --
头像
a5dedecms织梦建站培训靠谱吗?
« 上一篇 2025-12-18
dede arclist标签如何修改?
下一篇 » 2025-12-18

相关文章

取消
微信二维码
支付宝二维码

目录[+]