-
字符串表示方式:
- 在C语言中,字符串实际上是一个字符数组(字节数组),并且以空字符
\0
结尾。例如,字符串"RUNOOB"
实际上在内存中表示为{'R', 'U', 'N', 'O', 'O', 'B', '\0'}
。 - 这个
\0
终止符告诉标准库函数(如printf()
、strlen()
等)字符串在哪里结束。
- 在C语言中,字符串实际上是一个字符数组(字节数组),并且以空字符
-
防止未定义行为:
- 如果没有正确地添加
\0
终止符,使用这些标准库函数时可能会导致未定义行为。例如,printf("%s", str)
会继续读取内存直到找到一个\0
,这可能导致读取到不相关的内存区域,甚至引发程序崩溃或安全漏洞(如缓冲区溢出攻击)。
- 如果没有正确地添加
1. 使用示例1
假设你有一个长度为5的字符串 "hello"
,你需要至少6个字节的空间来存储它(包括 \0
终止符)。
char str[6] = "hello"; // 正确,隐式包含 \0
// 或者
char str[] = "hello"; // 正确,编译器自动计算大小并包含 \0
如果只分配了5个字节:
char str[5] = "hello"; // 错误,没有空间留给 \0
在这种情况下,str
不会被正确地视为一个C字符串,因为缺少终止符 \0
。
2. 使用示例2
2.1 错误示例1
char buffer[5];
sprintf(buffer, "hello"); // 错误,buffer 只有 5 字节,不足以容纳 "hello\0"
2.2 错误示例2
char buffer[7];
int num = 4;
sprintf(buffer, "hello %d", num); // 错误,buffer 只有7字节,不足以容纳 "hello 5\0"
2.3 正确示例
/* 恰巧开辟缓冲区 */
char buffer[8];
int num = 4;
sprintf(buffer, "hello %d", num); // 错误,buffer 只有7字节,不足以容纳 "hello 5\0"
/* 开辟稍微大一点的缓冲区 */
char buffer[256];
int num = 4;
sprintf(buffer, "hello %d", num); // 错误,buffer 只有7字节,不足以容纳 "hello 5\0"
3. char *str和char str2[]的用法
3.1 char *str的使用场景
函数参数传递:当需要将字符串传递给函数时,通常使用指针,因为指针只需要传递地址,效率较高。
void printString(const char *str) {
printf("%s\n", str);
}
结构体中使用字符串:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 定义一个包含字符指针的结构体
struct Person {
char *name; // 指向字符串的指针
int age;
};
int main() {
// 动态分配内存并初始化结构体实例
struct Person person1;
person1.name = (char *)malloc(50 * sizeof(char)); // 分配50字节的内存
if (person1.name == NULL) {
fprintf(stderr, "Memory allocation failed\n");
return 1;
}
strcpy(person1.name, "Alice");
person1.age = 30;
// 打印结构体内容
printf("Name: %s\n", person1.name);
printf("Age: %d\n", person1.age);
// 修改结构体中的字符串
strcpy(person1.name, "Bob");
// 再次打印结构体内容
printf("Name: %s\n", person1.name);
printf("Age: %d\n", person1.age);
// 释放分配的内存
free(person1.name);
return 0;
}
3.2 char str2[]的使用场景
固定大小的字符串:当你知道字符串的最大长度并且不需要动态调整大小时,使用字符数组更为合适。
char buffer[100];
fgets(buffer, sizeof(buffer), stdin); // 从标准输入读取最多99个字符
结构体中使用字符串:
#include <stdio.h>
#include <string.h>
// 定义一个包含字符数组的结构体
struct Person {
char name[50]; // 假设名字的最大长度为49个字符(包括终止符)
int age;
};
int main() {
// 创建并初始化结构体实例
struct Person person1 = {"Alice", 30};
// 修改结构体中的字符串
strcpy(person1.name, "Bob");
// 打印结构体内容
printf("Name: %s\n", person1.name);
printf("Age: %d\n", person1.age);
return 0;
}
总结:当能大致估计字符串的长度时,直接使用字符数组;当我估计不到字符串有多长时,直接使用字符指针;