You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中解引用char*数组并存储到char**数组的问题

问题分析与解决方案

你遇到的核心问题是栈局部变量的复用与生命周期问题:循环内部声明的b是栈上的数组,每次循环迭代时,它在栈内存中的位置是固定不变的。所以a[i] = b;实际上是把同一个栈地址赋值给了所有a[i]。当循环结束后,这个地址里留存的是最后一次循环对b的赋值结果,因此所有printf调用都会输出最后那组"hello world"。

至于你尝试的*a[i] = *b和**a[i] = **b导致段错误的原因:char **a[16];只是声明了一个指针数组,但数组里的每个元素都是未初始化的野指针。直接解引用野指针去赋值,必然会访问非法内存,触发段错误。即使a[i]指向有效内存,**a[i] = **b试图修改字符串常量的内容也是不允许的——字符串常量存储在只读数据段,修改它会导致未定义行为。

下面给出两种可行的解决方案:

方案1:动态分配独立的指针数组(堆内存)

每次循环为a[i]分配一块新的堆内存,用来存储指针数组,这样每个a[i]指向独立的内存区域:

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

int main() {
    char ** a[16];
    // 初始化所有元素为NULL,避免野指针
    memset(a, 0, sizeof(a));
    int i;
    for (i = 0; i < 5; i++) {
        // 分配能容纳3个char*的内存
        char **b = malloc(3 * sizeof(char*));
        if (!b) { // 检查malloc是否成功
            perror("malloc failed");
            return 1;
        }
        b[2] = '\0';
        b[0] = "foo";
        b[1] = "bar";
        if (i == 4) {
            b[0] = "hello";
            b[1] = "world";
        }
        a[i] = b;
    }

    // 测试输出
    printf("%s %s\n", a[0][0], a[0][1]);
    printf("%s %s\n", a[4][0], a[4][1]);

    // 记得释放堆内存,避免泄漏
    for (i = 0; i < 5; i++) {
        free(a[i]);
    }
    return 0;
}

这里字符串常量是全局只读的,直接赋值指针即可,不需要复制字符串内容。

方案2:使用二维指针数组(栈内存,适合数量固定的场景)

如果提前知道需要存储的数组数量(比如这里的5个),可以直接声明二维指针数组,让每个a[i]都是独立的指针数组,完全避免指针复用问题:

#include <stdio.h>

int main() {
    // 声明5个指针数组,每个数组包含3个char*
    char *a[5][3];
    int i;
    for (i = 0; i < 5; i++) {
        a[i][2] = '\0';
        a[i][0] = "foo";
        a[i][1] = "bar";
        if (i == 4) {
            a[i][0] = "hello";
            a[i][1] = "world";
        }
    }

    // 测试输出
    printf("%s %s\n", a[0][0], a[0][1]);
    printf("%s %s\n", a[4][0], a[4][1]);

    return 0;
}

这种方法不需要动态分配内存,也没有内存泄漏风险,实现更简洁。


内容的提问来源于stack exchange,提问作者0xREDACTED

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 20:13:14