`char*` 和 `char[]` 在C中都是用于处理字符数据的,但它们之间存在一些重要的区别:
1. 内存分配
// 在堆上分配内存
char* str = new char[10];
strcpy(str, "Hello"); // 使用C语言风格的字符串函数
delete[] str; // 需要手动释放内存
// 在栈上分配
char* ch = "Hello world"; // 直接赋值
// 定义数组,有初值决定大小,或者手动指定数组大小
char str[] = "hello world";
char str1[10];
- `char*`:可以指向任何位置的字符数据,包括静态存储区、动态分配的内存或栈上的字符数组。
- `char[]`:是一个数组类型,其大小在编译时确定,并存储在栈上。
2. 内存生命周期
- `char*`:可以指向具有不同生命周期的内存,例如全局或堆上分配的内存。
- `char[]`:其生命周期仅限于定义它的代码块。
3. 内存释放
- `char*`:如果指向动态分配的内存(使用 `new` 或 `malloc`),需要手动释放(使用 `delete` 或 `free`)。
- `char[]`:不需要手动释放,它在离开作用域时自动释放。
4. 可变性
// 定义 指针ch
const char* ch = "ABCD";
cout << ch<<endl;
// 改变指向
ch = "inwd";
cout << ch << endl;
// 定义数组ch1
char ch1[] = "ABCD";
cout << ch1 << endl;
// 修改数组中某个元素值
ch1[0] = 'a';
cout << ch1 << endl;
// 定义数组 ch2
char ch2[] = "abcd";
// 定义指针ch3,指向ch1
char* ch3 = ch1;
cout << ch3 << endl;
// 修改指针ch3的指向,从ch1指向ch2
ch3 = ch2;
cout << ch3 << endl;
- `char*`:可以被重新赋值为指向不同的内存位置。
- `char[]`:一旦初始化后,不能改变其指向的内存位置。
5. 大小
sizeof函数
char sz[10];
// 大小为10。 打印10
cout << sizeof(sz) << endl;
// 赋值前9个字节
for (int i = 0; i < 9; i++)
{
sz[i] = 'a';
}
// 最后一个 字节字符串结束符 \0 。 否则打印末尾是乱码
sz[9] = '\0';
cout << sz << endl;
char ch2[] = "abcd";
char* ch3 = ch1;
// ch2为数组,大小4+1 = 5
cout << sizeof(ch2) << endl;
// ch3为指针,大小固定为指针大小,4或8(x64下)
cout << sizeof(ch3) << endl;
- `char*`:可以指向大小可变或不明确的字符数据。
- `char[]`:数组的大小是固定的,并且在声明时必须指定或由初始化的字符串确定。
6. 初始化
- `char*`:可以被初始化为 `NULL` 或指向一个字符串字面量。
- `char[]`:可以被初始化为一个字符串字面量,并且数组的大小可以由字符串的长度加1(为终止的空字符`'\0'`留出空间)确定。
7. 字符串操作
- `char*`:经常作为参数传递给C语言风格的字符串操作函数,如 `strlen`、`strcpy` 等。
- `char[]`:可以直接使用C++标准库中的字符串操作函数。
8. 数组越界
- `char*`:使用时需要手动管理,容易发生越界错误。
- `char[]`:在使用现代C++特性时(如 `std::string`),可以避免越界错误。
9. 可读性
- `char*`:在复杂的表达式中可能难以理解。
- `char[]`:数组的语法更直观,易于理解其大小和作用域。