c++ - 通过更高级别的结构访问子变量

标签 c++ c

如果我有这些结构:

typedef struct { int x; } foo;
typedef struct { foo f; } bar;

通常你会通过 b.f.x 访问 x,但是有没有办法设置它,这样你就可以访问元素 x 而无需引用f?

bar b;
b.x = ...

我的第一个直觉是你不能,因为如果两个子结构都有一个成员 x 并且我无法弄清楚编译错误会是什么,那么可能会发生名称冲突。不过,我记得我曾在一些可行的框架中工作过。

在 C++ 中,我曾经在一个存在 bar 的框架中工作过,您可以从不同的类作为成员变量 this->x 访问它的成员。我正在尝试弄清楚如何做到这一点。

最佳答案

你可以用 C11:

§ 6.7.2.1 -- 11

An unnamed member whose type specifier is a structure specifier with no tag is called an anonymous structure; an unnamed member whose type specifier is a union specifier with no tag is called an anonymous union. The members of an anonymous structure or union are considered to be members of the containing structure or union. This applies recursively if the containing structure or union is also anonymous.

所以这段代码可能工作:

#include <stdio.h>

typedef struct { int x; } foo;
typedef struct { foo; } bar;

int main(void)
{
    bar b;
    b.x = 1;
    printf("%d\n", b.x);
}

这里的问题是,不同的编译器在我的测试中对于 typedef 是否可以作为没有标签的 struct 说明符是可以接受的 标准规定:

§ 6.7.8 -- 3

In a declaration whose storage-class specifier is typedef, each declarator defines an identifier to be a typedef name that denotes the type specified for the identifier in the way described in 6.7.6. [...] A typedef declaration does not introduce a new type, only a synonym for the type so specified.

(强调我的)——但是 synonym 是否也意味着 typdef-name 说明符可以替换为 struct 说明符gcc 接受这个,clang 不接受。

当然,没有办法用这些声明来表达foo类型的整个成员,你牺牲了你的命名成员f

关于您对名称冲突的疑问,当您在 bar 中放置另一个 int x 时,gcc 必须这样说:

structinherit.c:4:27: error: duplicate member 'x'
 typedef struct { foo; int x; } bar;
                           ^

为避免歧义,您可以重复结构,可能#defined 作为宏,但当然,这看起来有点难看:

#include <stdio.h>

typedef struct { int x; } foo;
typedef struct { struct { int x; }; } bar;

int main(void)
{
    bar b;
    b.x = 1;
    printf("%d\n", b.x);
}

但是任何符合标准的编译器都应该接受这个代码,所以坚持这个版本。

很遗憾,我更喜欢 gcc 接受的语法,但由于标准的措辞并没有使其 明确 允许这个,唯一安全的赌注是假设它是被禁止的,所以 clang 不应该归咎于此......

如果你想通过 either b.x or b.f.x 引用 x ,您可以像这样使用额外的匿名 union :

#include <stdio.h>

typedef struct { int x; } foo;
typedef struct {
    union { struct { int x; }; foo f; };
} bar;

int main(void)
{
    bar b;
    b.f.x = 2;
    b.x = 1;
    printf("%d\n", b.f.x); // <-- guaranteed to print 1
}

不会因为

而导致别名问题

§ 6.5.2.3 -- 6

One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members

关于c++ - 通过更高级别的结构访问子变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44523717/

相关文章:

c++ - 在函数中使用 cin/cout 流

c++ - 如何在 C++ 中修复从字符串常量到 'char*' 的警告弃用转换?

c++ - 使用 Boost Coroutines 实现多任务调度器和执行器

内存中的C指针数据结构

c++ - 将外部 .asm 文件包含到 C++ 代码中

c++ - 如何初始化一个很长的数组?

c - 如何在运行时获取数据和bss地址空间(在Unix C程序中)

c - 链表 : Initialize Head with function?

c - 如何将代码的输出重定向到代码块中的 pdf 或文本文件?

c - 如何在C中的char数组中存储2位整数值和浮点值