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

C语言中取结构体数组成员地址的&(p_t->x)表达式是否合法?

关于C语言中&(p_t->x)表达式合法性的解析

先看测试代码:

struct test {
    int x[3];
};

int main() {
    struct test t;
    t.x[0] = 1;
    t.x[1] = 2;
    t.x[2] = 3;
    
    struct test *p_t;
    p_t = &t;

    printf("p_t->x: %p\n", p_t->x);
    printf("&(p_t->x[0]): %p\n", &(p_t->x[0]));
    printf("&(p_t->x): %p\n", &(p_t->x));
    return 0;
}

运行输出:

p_t->x: 0x7ffe49dd2abc
&(p_t->x[0]): 0x7ffe49dd2abc
&(p_t->x): 0x7ffe49dd2abc

核心疑问:&(p_t->x)是否合法?是否属于未定义行为?

答案是:这个表达式完全合法,不属于未定义行为,只是它的类型和常规写法有差异,地址数值相同是C语言数组内存布局特性导致的结果。

详细解析三种表达式的区别

  • p_t->x:访问结构体数组成员时,数组名会自动退化为指向首元素的指针,类型是int *,指向t.x[0]的内存地址。
  • &(p_t->x[0]):直接取数组第一个元素的地址,类型也是int *,和上面的表达式指向同一个内存位置。
  • &(p_t->x):这里的p_t->x是完整的数组类型(int[3]),取数组本身的地址,得到的是指向数组的指针,类型为int (*)[3]。

为什么地址数值相同?

在内存中,数组的起始地址就是其首元素的起始地址,所以三者打印出来的地址值完全一致,但类型差异会影响后续指针运算:

  • 对int *类型指针执行+1,会偏移一个int的长度(通常4字节);
  • 对int (*)[3]类型指针执行+1,会偏移整个数组的长度(通常12字节)。

结论

如果代码目标是获取数组首元素的指针,&(p_t->x)虽然地址值正确,但类型不符合预期,属于不规范写法。推荐使用p_t->x或&p_t->x[0],这两种写法更直观,也契合代码的实际意图。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 10:33:46