这个 [1] 在结构声明末尾的目的是啥?

Posted

技术标签:

【中文标题】这个 [1] 在结构声明末尾的目的是啥?【英文标题】:What's the purpose of this [1] at the end of struct declaration?这个 [1] 在结构声明末尾的目的是什么? 【发布时间】:2018-04-15 15:11:18 【问题描述】:

我正在窥探我的 MSP430 微控制器的头文件,我在<setjmp.h> 中遇到了这个问题:

/* r3 does not have to be saved */
typedef struct

    uint32_t __j_pc; /* return address */
    uint32_t __j_sp; /* r1 stack pointer */
    uint32_t __j_sr; /* r2 status register */
    uint32_t __j_r4;
    uint32_t __j_r5;
    uint32_t __j_r6;
    uint32_t __j_r7;
    uint32_t __j_r8;
    uint32_t __j_r9;
    uint32_t __j_r10;
    uint32_t __j_r11;
 jmp_buf[1]; /* size = 20 bytes */

我知道它声明了一个匿名结构并将 typedef 定义为 jmp_buf,但我无法弄清楚 [1] 的用途。我知道它声明 jmp_buf 是一个包含一个成员(这个匿名结构的)的数组,但我无法想象它的用途。有什么想法吗?

【问题讨论】:

可能与衰减成指针有关? 最后的评论似乎完全错误...... 【参考方案1】:

这是在 C 中创建“引用类型”的常用技巧,其中将其用作函数参数会导致单个元素数组降级为指向其第一个元素的指针,而程序员无需显式使用 &运营商获取其地址。在声明的地方,它是一个真正的堆栈类型(不需要动态分配),但是当作为参数传递时,被调用函数接收指向它的指针,而不是副本,因此它的传递成本很低(如果不是,可以被调用函数改变) const)。

GMP 对其mpz_t 类型使用相同的技巧,这在此处很关键,因为该结构管理指向动态分配内存的指针; mpz_init 函数依赖于获取指向结构的指针,而不是它的副本,或者它根本无法初始化它。类似地,许多操作可以调整动态分配的内存大小,如果它们不能改变调用者的结构,这将不起作用。

【讨论】:

它还可以防止通过=进行复制。 这太恶心了。一旦最短时间过去,我会接受这个答案。感谢您的帮助! @Alexander:当像这样通过typedef 封装时,它并没有那么恶心。是的,这样做会有点糟糕,但如果你有一个微弱的不透明类型,API 用户永远不需要考虑引用与非引用语义(它应该总是通过参考),这是一种将自动参考语义添加到原本缺乏它的语言的合理方法。如果用户编写自己的接收类型的 API,它甚至可以工作,因为在 C 中,声明您接受一个数组作为参数实际上意味着您接受一个指针;一切都“正常工作”。 @ShadowRanger 这是一个聪明的把戏,但... otherwise lacks it 是它的毛病。 C 的局限性,而不是解决方法本身 IMO 太恶心了。第一次使用 GMP 我无法理解它是如何工作的,因为这些数字显然是按值传递的。我不得不深入研究 GMP 标头来解决它。它只是在实际上已经知道 C 的人面前飞行。然后你必须记住哪些参数是按值传递的,哪些是引用的,而不是仅仅在代码中寻找*

以上是关于这个 [1] 在结构声明末尾的目的是啥?的主要内容,如果未能解决你的问题,请参考以下文章

nameidentifier 声明的目的是啥?

在 Angular 中声明视图时添加额外的 'views:'foo':' 的目的是啥?

声明 mongoose.Schema.Types.ObjectId 的目的是啥?

嵌入式 STM32 NVIC_InitTypeDefNVIC_InitStructure; 上面这个结构声明是啥意思?

将方法参数声明为 final 的目的是啥? [复制]

指针变量声明了后其默认值是啥呢,啥时候它的值才为“null”空呢?