当前位置: 首页 > 知识库问答 >
问题:

C11 - 将指针到结构转换为结构的匿名第一个成员

萧萧迟
2023-03-14

C标准规定:

指向结构对象的指针,经过适当的强制转换,指向其初始成员(如果该成员是位字段,则指向其所在的单元),反之亦然。

如果有问题的结构的第一个成员是匿名结构/联合,是否有任何可能(并且定义良好)的方法在C11中执行这种“合适的转换”?或者如果包含的结构是匿名的,则执行“反之亦然”的反向转换?

我猜想,转换为与匿名结构具有相同成员序列的非匿名结构会使它无法很好地定义,因为它们不兼容,因此不能保证具有相同的内存布局。

然而,C标准规定:

此外,如果在单独的翻译单元中声明的两个结构、联合或枚举类型的标记和成员满足以下要求,则它们是兼容的:如果一个用标记声明,则另一个用相同的标记声明。如果两者都在各自的翻译单位内完成,则以下附加要求适用:其成员之间应进行一对一的通信

我们可以尝试将这个规则应用于匿名结构吗?比方说,如果我们有以下设置:

标题.h:

struct container {
    struct {
        int a;
        char b;
    };
};

void print(struct container *pcontainer);

sep. c:

#include <stdio.h>
#include "header.h"

void print(struct container *pcontainer){
    printf("%d\n", ((struct { int a; char b; }*)pcontainer)->a);
}

main.c

#include "header.h"

int main(void){
    struct container container, *pcontainer;

    pcontainer = &container;
    pcontainer->a = 1;

    print(pcontainer);

    return 0;
}

(这在gcc(GCC)4.8.3 20140911上编译并输出1)。

考虑在< code>print函数内的转换中使用的匿名结构,以及在< code>main.c中结束的< code>struct容器的第一个成员的匿名结构。它们可以被认为是“在单独的翻译单元中声明的类型”吗?此外,它们真的满足所有其他兼容性要求吗,还是我误解了什么?

共有1个答案

和光启
2023-03-14

什么是翻译单元:

5.1.1.1程序结构

  1. 一个C程序不需要全部同时翻译。在本国际标准中,程序文本以称为源文件(或预处理文件)的单位保存。源文件以及通过预处理指令#include包含的所有头文件和源文件称为预处理翻译单元。预处理后,预处理翻译单元称为翻译单元

所以c文件加上预处理后的头形成了一个翻译单元。让我们以sep. c和head. h组成的翻译单元为例。它包含结构{int a; char b;}的两个声明,一个在结构容器中,另一个在函数print中。这些结构在同一个翻译单元中声明

6.2.7兼容型和复合型

  1. 如果两种类型的类型相同,则它们具有兼容的类型。确定两种类型是否兼容的其他规则在6.7.2中描述了类型说明符,6.7.3中描述了对于类型限定符,6.7.6中描述了关于声明符。此外,在单独的翻译中声明的两个结构、联合或枚举类型

其余的文本是指在单独的翻译单元中声明的类型。

由于结构不在单独的翻译单元中声明,因此它们不属于6.2.7规则的范围。

因此,在我的解释中,struct容器中的一个和print()中的转换中的另一个结构是不兼容的。

 类似资料:
  • 问题内容: 如果我有: 上面是固定的-我不能更改foo或bar。另外,baz必须在bar内转换回foo struct指针。如何将&foo {}强制转换为interface {},以便在调用bar时可以将其用作参数? 问题答案: 要打开到一个很简单: 为了返回到,您可以执行 类型断言 : 或 类型开关 (类似,但可以是多种类型则很有用):

  • 考虑以下代码: 我必须定义一个回调函数,我想在该函数中使用一些附加信息。我定义了自己的结构并将成员的地址传递给函数。在函数中,我想通过强制转换“检索”整个结构,但指针似乎不匹配,我得到了错误的结果。我想我在选演员时做错了什么,但我不确定是什么?

  • 假设代码是用c11编译的,并且启用了严格别名。 我不是在寻找一种不同的方法,我想专注于这个具体的问题,以及它是否可行或为什么不可行。 (如果我无意中犯了一些无关的错误,请告诉我,我会改正的) C11标准说: 6.2.5.28所有指向结构类型的指针应具有彼此相同的表示和对齐要求。 6.7.2.1.6结构是由成员序列组成的类型,其存储按有序顺序分配 这意味着结构A和B中指针的大小和对齐方式相同。 结构

  • 我正在学习如何在C中使用并写了以下示例: 问:是否保证在所有情况下指向一个结构的指针都是指向它的第一个元素的完全相同的指针? 在这种特殊的情况下,它能像我预期的那样工作,但我不确定它是否能得到保证。编译器可以在开始时插入一些填充吗? 我唯一能找到的关于结构类型布局的是N1570的类型: 结构类型描述了一组按顺序分配的非空成员对象(在某些情况下,还包括一个不完整的数组),每个对象都有一个可选的指定名

  • 问题内容: http://play.golang.org/p/vhaKi5uVmm [第一个问题] 我们如何以及为什么需要这种看起来很奇怪的结构?它是空结构还是匿名结构?我用谷歌搜索,但是找不到正确的答案或说明文档。 原始资料来自Andrew Gerrand的演讲 http://nf.wh3rd.net/10things/#10 这里 完成是struct {}类型的通道 所以我尝试了 但这是行不通

  • 问题内容: 我不理解以下代码的行为。在创建作为结构指针切片的匹配结构列表时,代码始终会打印原始数组的最后一个元素(实际上不是匹配项),它会打印12和12。但是,如果将匹配项更改为[]窗口小部件代替[] * Widget,然后将输出10和11。 为什么是这样? 问题答案: 那是因为当您使用指针时,您将添加到数组。 请注意,实际上这是循环中使用的局部变量,因此,这不是您要添加到数组中的地址。 (即使变