char与string在C语言中究竟有何区别?

99ANYc3cd6
预计阅读时长 21 分钟
位置: 首页 C语言 正文

第一部分:char - 字符类型

char 是 C 语言中的一个基本数据类型,它的全称是 "character"(字符),它的本质是一个小的整数

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

char 的存储

在内存中,char 类型通常占用 1 个字节(8 bits),它被用来表示一个字符,'A', 'b', '1', 等。

关键点: 计算机不直接存储字符 'A',而是存储它对应的数字编码,最常用的编码是 ASCII (American Standard Code for Information Interchange)

  • 'A' 的 ASCII 码是 65
  • 'B' 的 ASCII 码是 66
  • 'a' 的 ASCII 码是 97
  • '0' 的 ASCII 码是 48

这意味着,你可以对 char 类型进行算术运算。

#include <stdio.h>
int main() {
    char c1 = 'A';
    char c2 = 'B';
    // 输出字符
    printf("c1 is: %c\n", c1); // %c 是格式化输出字符的占位符
    // 输出字符对应的 ASCII 码
    printf("ASCII code of c1 is: %d\n", c1); // %d 是格式化输出整数的占位符
    // 算术运算
    char c3 = c1 + 1;
    printf("c1 + 1 is: %c\n", c3); // 输出 'B'
    return 0;
}

char 的两种形式

C 语言中的 char 有两种形式,它们在语法上几乎一样,但用途不同:

c语言 char string
(图片来源网络,侵删)
  1. char: 可以存储正负值(范围通常是 -128 到 127),它既可以表示字符,也可以作为一个小整数使用。
  2. unsigned char: 只能存储非负值(范围通常是 0 到 255),当你只关心原始字节,而不关心它是否代表一个可打印字符时(例如处理图像文件、网络数据包),通常会使用 unsigned char

第二部分:C 语言中的字符串

这是初学者最容易出错的地方。C 语言本身并没有一个原生的 "string"(字符串)数据类型,所谓的 "字符串" 是通过字符数组来实现的。

字符串的表示:以 '\0' 结尾的字符数组

C 语言中的字符串被定义为一个字符数组,并且这个数组的最后一个元素必须是空字符(Null Character),写作 '\0'

  • '\0' 的 ASCII 码是 0
  • '\0' 是一个特殊的标记,它告诉字符串处理函数(如 printf, strlen 等):“字符串到这里就结束了”。

示例:

#include <stdio.h>
int main() {
    // 方式一:显式地包含 '\0'
    char str1[] = {'H', 'e', 'l', 'l', 'o', '\0'};
    printf("str1: %s\n", str1); // %s 是格式化输出字符串的占位符
    // 方式二:编译器自动添加 '\0' (最常用)
    // 当你用双引号 "" 定义一个字符串字面量时,C 编译器会自动在末尾加上 '\0'
    char str2[] = "Hello";
    // str2 在内存中实际是: {'H', 'e', 'l', 'l', 'o', '\0'}
    // 方式三:使用指针
    // 这里 "Hello" 仍然是一个以 '\0' 结尾的字符数组,str3 指向它的第一个元素 'H'
    char *str3 = "Hello";
    return 0;
}

字符串 vs. 字符数组

虽然字符串是字符数组,但并非所有字符数组都是字符串。

c语言 char string
(图片来源网络,侵删)
  • 字符串:必须以 '\0'
  • 字符数组:只是一个字符的集合,不一定以 '\0'

示例:

#include <stdio.h>
#include <string.h> // 用于 strlen 函数
int main() {
    // 这是一个字符串,因为它以 '\0' 
    char my_string[] = "Hi";
    printf("Length of my_string: %zu\n", strlen(my_string)); // 输出 2
    // 这只是一个字符数组,不是字符串
    char my_chars[5] = {'H', 'i', '!', '!', '!'};
    // my_chars 没有以 '\0' 
    // 如果你尝试用 %s 输出它,会发生未定义行为
    // printf("my_chars: %s\n", my_chars); // 危险!可能会打印出乱码,甚至导致程序崩溃
    // 你可以像普通数组一样逐个字符访问
    my_chars[0] = 'J';
    printf("my_chars[0]: %c\n", my_chars[0]); // 输出 'J'
    return 0;
}

第三部分:char 数组与 char 指针

这两种方式都可以用来表示字符串,但它们有重要的区别。

char 数组 (Character Array)

  • 本质:一块连续的内存空间,用于存储字符(包括 '\0')。
  • 数组的内容可以被修改。
  • 内存位置:通常存储在上。
char greeting[50] = "Hello";
greeting[0] = 'J'; // 合法,可以修改内容
strcpy(greeting, "New Greeting"); // 合法,可以修改内容

char 指针 (Character Pointer)

  • 本质:一个变量,它存储的是字符串第一个字符的内存地址。
  • 指向一个字符串常量,通常不应该被修改。
  • 内存位置:指针变量本身在栈上,但它指向的字符串常量通常存储在只读数据段
char *message = "Hello";
// message[0] = 'J'; // 危险!这通常会导致未定义行为,因为 "Hello" 是一个常量,存储在只读内存区。
// strcpy(message, "New Message"); // 同样危险,不能修改它指向的内容。
// 你可以修改指针本身,让它指向别的地方
char another_message[] = "World";
message = another_message; // 合法,message 指向 "World"

总结区别:

特性 char greeting[] char *message
内存分配 编译时分配固定大小的空间(在栈上) 指针变量在栈上,指向别处(通常是只读区)
大小 固定,由声明决定 指针大小固定(通常是4或8字节),指向的字符串大小不固定
常见用途 存储和修改可变长度的字符串 传递字符串、指向字符串常量

第四部分:常用的字符串处理函数

为了方便操作字符串,C 标准库 <string.h> 提供了一系列函数,使用这些函数时,请确保目标缓冲区足够大,避免缓冲区溢出

  • strlen(str): 获取字符串长度(不包括 '\0')。
  • strcpy(dest, src): 将 src 字符串复制到 destdest 必须足够大。
  • strncpy(dest, src, n): 安全一点的复制,最多复制 n 个字符。
  • strcat(dest, src): 将 src 字符串拼接到 dest 末尾。dest 必须足够大。
  • strcmp(s1, s2): 比较两个字符串,返回 0(相等)、正数(s1 > s2)、负数(s1 < s2)。
  • sprintf(buffer, format, ...): 格式化数据并写入字符串缓冲区,类似 printf,但输出目标是字符串。

示例:

#include <stdio.h>
#include <string.h>
int main() {
    char first_name[50] = "John";
    char last_name[] = "Doe";
    char full_name[100]; // 确保空间足够
    // 1. 拼接字符串
    strcpy(full_name, first_name); // full_name 现在是 "John"
    strcat(full_name, " ");       // full_name 现在是 "John "
    strcat(full_name, last_name);  // full_name 现在是 "John Doe"
    printf("Full Name: %s\n", full_name);
    // 2. 获取长度
    printf("Length of full_name: %zu\n", strlen(full_name)); // 输出 8
    // 3. 比较字符串
    if (strcmp(first_name, "John") == 0) {
        printf("First name is indeed John.\n");
    }
    return 0;
}

第五部分:现代 C++ 中的 std::string

如果你正在使用 C++,强烈建议使用 std::string 而不是 C 风格的字符数组。std::string 是一个类,它为你处理了所有底层的内存管理、大小调整和拼接等操作,更加安全和方便。

#include <iostream>
#include <string> // C++ string header
int main() {
    // C++ std::string
    std::string s1 = "Hello";
    std::string s2 = " World";
    // 可以直接拼接,无需担心缓冲区
    std::string s3 = s1 + s2;
    std::cout << "s3: " << s3 << std::endl;
    // 可以轻松获取长度
    std::cout << "Length of s3: " << s3.length() << std::endl;
    // 可以像数组一样访问和修改
    s3[0] = 'J';
    std::cout << "Modified s3: " << s3 << std::endl;
    return 0;
}
概念 描述 关键点
char 基本数据类型,表示一个字符,本质是1字节的整数。 占用1字节,可以进行算术运算。
字符串 C 语言中没有原生类型,用字符数组实现。 必须以'\0'结尾作为结束标记。
char[] 字符数组,用于存储字符串,内容可修改,大小固定。 存储在栈上,适合存储和修改可变字符串。
*`char`** 字符指针,通常指向字符串常量,内容不可修改。 指向只读区,适合传递字符串或指向常量。
<string.h> C 标准库,提供字符串操作函数。 使用时务必注意缓冲区大小,防止溢出。
std::string C++ 标准库,安全的字符串类。 自动管理内存,是 C++ 中处理字符串的首选。
-- 展开阅读全文 --
头像
C语言break在switch中必须用吗?
« 上一篇 01-14
织梦付费可见功能为何不显示?
下一篇 » 01-14

相关文章

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