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
相关产品推荐
相关产品推荐

