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

C语言函数中结构体数组元素访问的二级指针误用问题

二级指针访问结构体数组的常见误区

首先定义了如下结构体:

typedef struct counter_Nval
{
    systs_t N;
    uint16_t cntr;
} countN_t;

为了分配该结构体的数组,我将指向该结构体的二级指针传入函数:

extern size_t __count_shnnr_N(size_t len, my_type_array *arr, countN_t **nNs)
{
    size_t ln = 1;
    size_t tmp = 1;

    *nNs = malloc(sizeof(**nNs) * ln--);

    nNs[ln]->N = arr[ln].N;
    nNs[ln]->cntr = 1;


    while (ln++ < len-1)
    {
        if (arr[ln].N == (*nNs+tmp-1)->N)
        {
            (*nNs+tmp-1)->cntr++;
        }
        else
        {
            *nNs = realloc(*nNs, sizeof(**nNs) * ++tmp);
            (*nNs+tmp-1)->N = arr[ln].N;
            (*nNs+tmp-1)->cntr = 1;
        }
    }
    return tmp;
}

实际使用中,当我尝试用nNs[tmp-1]->N替代(*nNs+tmp-1)->N访问结构体数组元素时,出现了Segmentation fault错误,但最初的nNs[ln]->N = arr[ln].N;和nNs[ln]->cntr = 1;却能正常运行。这两种写法难道不是等价的吗?我存在什么误区?


问题本质:混淆二级指针自身的偏移与指向的一级指针的偏移

你混淆了二级指针nNs本身的内存偏移,和它指向的一级指针(结构体数组的首地址)的内存偏移:

  • nNs是countN_t **类型,也就是指向指针的指针。nNs[x]等价于*(nNs + x),这里的偏移是针对nNs这个二级指针变量所在的内存地址进行的,而不是针对*nNs指向的结构体数组。
  • 最初的代码能运行是因为ln--后ln的值是0,nNs[0]等价于*nNs,也就是你用malloc分配的结构体数组的首指针,这时候nNs[0]->N和(*nNs)->N是完全等价的,自然能正常访问。
  • 但当tmp-1不为0时(比如tmp=2时tmp-1=1),nNs[1]会去访问nNs这个二级指针变量内存地址的下一个位置,而这个位置根本不是你分配的结构体数组的指针,属于非法内存访问,直接触发段错误。

正确的等价写法

如果你想用下标语法替代指针偏移,应该先解引用二级指针得到一级指针,再对一级指针用下标:

(*nNs)[tmp-1].N

或者保持原来的指针偏移写法:

(*nNs + tmp-1)->N

这两种才是真正等价的,因为它们都是对*nNs(结构体数组的首指针)进行偏移访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:17:19