C 语言中,char 数组和 char 指针之间有一些重要的区别,主要体现在内存管理和语法行为上。char 数组是一个固定大小的连续内存块,大小在编译时确定。char 指针是一个指向内存地址的变量,可以指向不同的内存区域,大小在运行时可以改变。两者之间的主要区别在于内存分配、修改和管理的方式。

1、定义与内存分配

1)char 数组

数组是固定大小的,分配内存时它会根据数组的大小分配连续的内存空间。数组的大小在编译时确定。

#include <stdio.h>

int main() {
    // 定义一个长度为10的字符数组
    char arr[10];

    // 给数组中的每个元素赋值
    arr[0] = 'H';
    arr[1] = 'e';
    arr[2] = 'l';
    arr[3] = 'l';
    arr[4] = 'o';
    arr[5] = ',';
    arr[6] = ' ';
    arr[7] = 'W';
    arr[8] = 'o';
    arr[9] = 'r';

    // 输出字符数组的内容
    printf("字符数组内容: %s\n", arr);

    return 0;
}

2)char 指针

指针变量用于存储地址。它不直接存储数据,而是存储数据的地址。指针本身不负责分配内存,通常通过动态分配内存来使用。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char *ptr;  // ptr 是一个指针,指向某个 char 类型的数据

    // 动态分配内存空间,10 个 char 大小
    ptr = malloc(10 * sizeof(char));
    
    // 检查内存分配是否成功
    if (ptr == NULL) {
        printf("内存分配失败!\n");
        return 1;  // 返回非 0 值表示错误
    }

    // 使用 memset 初始化内存
    memset(ptr, 0, 10 * sizeof(char));  // 将分配的内存块初始化为 0

    // 给内存中的字符数组赋值
    strcpy(ptr, "Hello");

    // 打印字符串
    printf("ptr 指向的字符串: %s\n", ptr);

    // 释放动态分配的内存
    free(ptr);

    return 0;
}

2、常量与可变性

1)char 数组

数组是一个固定大小的结构,一旦定义,不能改变大小,元素数量是固定的。

#include <stdio.h>

int main() {
    char arr[] = "hello";  // 创建一个包含 "hello" 字符串和 null 终止符的字符数组
    printf("Array content: %s\n", arr);  // 输出数组内容
    printf("Array length (excluding null terminator): %lu\n", sizeof(arr) - 1);  // 输出数组长度,不包括 null 终止符
    return 0;
}

2)char 指针

指针指向的内存地址可以修改,可以使指针指向不同的内存区域或字符数组。

#include <stdio.h>

int main() {
    char *ptr = "hello";  // 指针初始化为指向字符串 "hello"
    printf("ptr points to: %s\n", ptr);  // 输出: ptr points to: hello

    ptr = "world";  // 改变指针 ptr 的指向,指向字符串 "world"
    printf("ptr now points to: %s\n", ptr);  // 输出: ptr now points to: world

    return 0;
}

3、语法差异

1)char 数组

数组名本身就代表了指向数组首元素的指针。

#include <stdio.h>

int main() {
    char arr[10];  // 声明一个包含 10 个元素的字符数组
    printf("%p\n", arr);  // 输出 arr 数组的地址,实际上是 arr[0] 的地址
    return 0;
}

2)char 指针

指针是一个明确的变量,需要被初始化并且指向某个地址。

#include <stdio.h>

int main() {
    // 定义一个字符数组
    char arr[] = "Hello, World!";
    
    // 声明一个指针 ptr,指向 arr 数组的首地址
    char *ptr = arr;
    
    // 输出 ptr 指向的地址
    printf("ptr points to address: %p\n", ptr);  // 输出 ptr 指向的地址,等同于 arr 的地址
    
    // 输出 arr 的地址
    printf("arr address: %p\n", arr);  // 输出 arr 数组的地址,应该与 ptr 指向的地址相同

    return 0;
}

4、内存大小

1)char 数组

数组的大小在声明时确定,并且存储在栈上。

#include <stdio.h>

int main() {
    // 定义并初始化一个大小为 10 的字符数组
    char arr[10] = {'H', 'e', 'l', 'l', 'o', '\0'};  // 字符数组,包含 10 个字符

    // 输出数组内容(打印字符串)
    printf("数组内容: %s\n", arr);  // 输出: Hello

    // 输出数组的第一个元素
    printf("第一个字符: %c\n", arr[0]);  // 输出: H

    return 0;
}

2)char 指针

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 在堆上分配一个大小为 10 的 char 数组
    char *arr = (char *)malloc(10 * sizeof(char));  
    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    arr[0] = 'H';
    arr[1] = 'e';
    arr[2] = 'l';
    arr[3] = 'l';
    arr[4] = 'o';
    arr[5] = '\0';

    printf("堆上的数组内容: %s\n", arr);  // 输出: Hello

    free(arr);  // 释放堆内存
    return 0;
}