C语言:通过引用修改结构体数组指针失败求助
问题:通过指针引用修改动态数组指针失败的排查与解决
初始问题代码
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct { int id_prod; } producto; void carga_producto(producto **productos) { int n = 1; printf("Productos before the calloc: %d\n ", productos); *productos = (producto *)calloc(1, sizeof(producto)); printf("Productos after the calloc: %d\n ", productos); while (n < 3) { printf("Value of n %d\n", n); producto *temp = realloc(*productos, (n + 1) * sizeof(producto)); *productos = temp; printf("position of temp: %d\n", temp); printf("Productos: %d\n ", productos); n++; } } int main() { producto *productos; carga_producto(&productos); }
运行结果
PS C:\Users\Usuario\Desktop\Esizon\test> ./datos.exe Productos before the calloc: 719321432 Productos after the calloc: 719321432 Value of n 0 position of temp: 1280342752 Productos: 719321432 Value of n 1 position of temp: 1280342752 Productos: 719321432
预期结果
PS C:\Users\Usuario\Desktop\Esizon\test> ./datos.exe Productos before the calloc: 719321432 Productos after the calloc: 426416321 Value of n 0 position of temp: 1280342752 Productos: 1280342752 Value of n 1 position of temp: 512346132 Productos: 512346132
核心误区:代码中打印的是productos(二级指针自身的内存地址,这个值在函数调用中不会改变),而非*productos(指向动态数组的一级指针,这才是需要观察的动态变化对象),导致误以为内存分配未生效。
修改后的尝试及问题
调整代码时错误打印了结构体实例的值而非指针地址,导致输出异常:
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct { int id_prod; } producto; void carga_producto(producto **productos) { int n = 0; printf("Productos before the calloc: %d\n ", productos); *productos = (producto *)calloc(1, sizeof(producto)); printf("Productos after the calloc: %d\n ", productos); while (n < 2) { printf("Value of n %d\n", n); producto *temp = realloc(*productos, (n + 1) * sizeof(producto)); *productos = temp; printf("position of temp: %d\n", *temp); // 错误:打印结构体值而非指针地址 printf("Productos: %d\n ", *productos); n++; } } int main() { producto *productos; carga_producto(&productos); }
运行结果
PS C:\Users\Usuario\Desktop\Esizon\test> ./datos.exe Productos before the calloc: -1270876504 Productos after the calloc: -1270876504 Value of n 0 position of temp: 0 Productos: -1072923936 Value of n 1 position of temp: 0 Productos: -1072923936
可行的返回指针方案
用户改用返回指针的方式实现功能,但希望解决通过引用修改指针的问题:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX 3 typedef struct { int id_prod; } producto; producto* carga_producto(int max) { producto *productos = calloc(1, sizeof(producto)); if (productos) { printf("Producto[0]: id=%d\n", productos->id_prod); for (int n = 1; n < max; n++) { producto *temp = productos; productos = realloc(temp, (n + 1) * sizeof(producto)); if (productos) productos[n].id_prod = n; else { printf("%s\n", "Something wrong"); free(temp); break; } printf("Producto[%d]: id=%d\n", n, productos[n].id_prod); } } return productos; } int main() { producto *productos = carga_producto(MAX); if (!productos) return 1; free(productos); return 0; }
正确的通过引用修改指针的实现
核心修正点:
- 打印
*productos(指向动态数组的一级指针地址)而非productos(二级指针自身地址) - 使用
%p格式符打印指针地址(符合C标准,避免%d导致的类型不匹配) - 增加内存分配失败的检查,避免空指针操作
#include <stdio.h> #include <stdlib.h> typedef struct { int id_prod; } producto; void carga_producto(producto **productos) { int n = 0; // 打印二级指针自身地址(该值始终不变) printf("Dirección de productos (puntero doble): %p\n", (void*)productos); // 初始化动态数组 *productos = calloc(1, sizeof(producto)); if (*productos == NULL) { printf("calloc falló\n"); return; } // 打印一级指针地址(动态数组的实际地址,会随分配变化) printf("Después de calloc, *productos: %p\n", (void*)*productos); while (n < 2) { printf("Valor de n: %d\n", n); // 扩容为n+2个元素(初始1个,循环2次后共3个) producto *temp = realloc(*productos, (n + 2) * sizeof(producto)); if (temp == NULL) { printf("realloc falló\n"); free(*productos); *productos = NULL; return; } *productos = temp; // 打印新数组地址 printf("Dirección de temp: %p\n", (void*)temp); // 打印更新后的一级指针地址 printf("*productos: %p\n", (void*)*productos); // 给新元素赋值验证有效性 (*productos)[n+1].id_prod = n+1; printf("Producto[%d] id: %d\n", n+1, (*productos)[n+1].id_prod); n++; } } int main() { producto *productos = NULL; carga_producto(&productos); if (productos != NULL) { // 验证数组所有元素 for (int i = 0; i < 3; i++) { printf("Producto[%d] id: %d\n", i, productos[i].id_prod); } free(productos); } return 0; }
运行说明
- 二级指针
productos的地址不会变化,因为它是函数参数(值传递的是main中指针的地址) - 一级指针
*productos的地址会随calloc和realloc动态变化,这才是动态数组的实际内存地址 - 使用
%p是打印指针地址的标准方式,避免类型不匹配问题
内容的提问来源于stack exchange,提问作者Acaymo Sánchez Ramirez
相关产品推荐
相关产品推荐

