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

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;
}

正确的通过引用修改指针的实现

核心修正点:

  1. 打印*productos(指向动态数组的一级指针地址)而非productos(二级指针自身地址)
  2. 使用%p格式符打印指针地址(符合C标准,避免%d导致的类型不匹配)
  3. 增加内存分配失败的检查,避免空指针操作
#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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:00:04