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

C语言:含重复指针数组的结构体指针指向异常且出现垃圾值

问题原因

createShoeFromDecks函数的参数是值传递,传入的deckOfCards是main函数中deckOfCards的临时副本。当函数执行完毕返回时,这个临时副本会被销毁,内存被释放。此时shoe中存储的所有卡片指针都指向了已经被释放的内存区域,属于野指针,访问时就会读取到随机的垃圾值。

解决方案

方案1:传递deck的指针(推荐,节省内存)

修改createShoeFromDecks的参数为指针类型,直接使用原deck的内存地址,避免临时副本被销毁:

static shoe createShoeFromDecks(deck *deckOfCards)
{
    shoe shoeOfCards;
    for (int nShoe = 0; nShoe < DECKAMOUNT; nShoe++) {
        uint offset = CARDSINADECK * nShoe;
        for (int rankNumer = 0; rankNumer < CARDSINADECK; rankNumer++) {
            uint posInArray = rankNumer + offset;
            // 取原deck中卡片的地址
            card *cardptr = &deckOfCards->cards[rankNumer];
            shoeOfCards.cards[posInArray] = cardptr;
        }
    }
    return shoeOfCards;
}

同时修改main函数中的调用方式,传入原deck的地址:

shoe shoeOfCards = createShoeFromDecks(&deckOfCards);

方案2:让shoe存储card结构体副本(更安全,无需关注生命周期)

修改shoe的结构体定义,将指针数组改为card结构体数组:

typedef struct shoe {
    uint topOfShoe;
    card cards[CARDSINASHOE]; // 直接存储card结构体,而非指针
} shoe;

然后修改createShoeFromDecks函数,直接复制card结构体:

static shoe createShoeFromDecks(deck deckOfCards)
{
    shoe shoeOfCards;
    for (int nShoe = 0; nShoe < DECKAMOUNT; nShoe++) {
        uint offset = CARDSINADECK * nShoe;
        for (int rankNumer = 0; rankNumer < CARDSINADECK; rankNumer++) {
            uint posInArray = rankNumer + offset;
            // 复制card结构体到shoe中
            shoeOfCards.cards[posInArray] = deckOfCards.cards[rankNumer];
        }
    }
    return shoeOfCards;
}

最后修改main函数中的printf语句,直接访问结构体成员(不再用指针箭头):

printf("%d %d \n", shoeOfCards.cards[i].rank, shoeOfCards.cards[i].suit);

方案对比

  • 方案1:内存占用小(仅存储指针),但需要保证原deck的生命周期长于shoe,否则仍会出现野指针问题。
  • 方案2:内存占用更大(复制8副牌的所有card结构体),但shoe的生命周期独立,无需依赖原deck,安全性更高。

内容的提问来源于stack exchange,提问作者Peter Petigru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:55:21