通过更高级别的结构访问子变量 [英] Accessing child variables through higher level structures

查看:88
本文介绍了通过更高级别的结构访问子变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我具有以下结构:

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

通常,您将通过<$访问 x c $ c> bfx ,但是有一种方法可以进行设置,以便您可以访问元素 x 而不引用 f

Normally you would access x through b.f.x, but is there a way to set this up so that you can access element x without referring to f?

bar b;
b.x = ...

我的第一个直觉是您不能,因为在那里如果两个子结构都具有成员x并且我无法弄清楚编译错误将是名称冲突的可能性。但是,我记得在可能的情况下在某些框架中工作。

My first intuition is that you can't since there would be a possibility for name conflicts if two sub structures both had a member x and I can't figure out what the compile error would be. However, I recall working in some frameworks where this was possible.

在C ++中,我曾在一个框架中工作过 bar 存在,您可以从其他类中将其作为成员变量 this-> x 访问。我试图弄清楚该怎么做。

In C++ I worked in a framework once where bar existed, and you could access its members as member variables this->x from a different class. I'm trying to figure out how that could be done.

推荐答案

您可以使用C11:

§6.7.2.1-11


一个未命名成员,其类型说明符是没有标签的结构说明符,称为
匿名结构;一个未命名的成员,其类型说明符是带有
no标记的联合说明符,称为匿名联合。匿名结构或联合
的成员被视为包含结构或联合的成员。如果包含结构或联合也是匿名的,则递归地应用

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规范。该标准指定:

The problem here is that different compilers disagree in my tests on whether a typedef is acceptable as a struct specifier with no tag The standard specifies:

第6.7.8节- 3


在声明中其存储类说明符为 typedef ,每个声明器将
标识符定义为typedef名称,该名称表示以6.7.6中描述的
方式为标识符指定的类型。 [...] typedef 声明不会引入新类型,仅这样指定类型的
同义词。

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.

(强调我的意思)-但是同义词的意思也就是 typdef-name 说明符可以与 struct说明符交换吗? gcc 接受, clang 不接受。

(emphasis mine) -- But does synonym also mean a typdef-name specifier is exchangeable for a struct specifier? gcc accepts this, clang doesn't.

当然,用这些声明无法表达 foo 类型的整个成员,而牺牲了命名成员 f

Of course, there's no way to express the whole member of type foo with these declarations, you sacrifice your named member f.

关于您对名称冲突的怀疑,这就是 gcc 所说的当您在中放入另一个 int x 时:

Concerning your doubt about name collisions, this is what gcc has to say when you put another int x inside bar:

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

为避免歧义,您可以重复此结构,可能是 #define d作为宏,但是,这看起来有点难看:

To avoid ambiguity, you can just repeat the struct, possibly #defined as a macro, but of course, this looks a bit ugly:

#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);
}

但是任何合格的编译器都应接受此代码,因此,请坚持使用此版本。

But any conforming compiler should accept this code, so stick to this version.

< opinion>这很遗憾,我喜欢 gcc 接受的语法更好,但是由于该标准的措辞并未使其明确允许使用 ,因此唯一的安全下注是假定其被禁止,因此 clang 不能怪这里...< / opinion>

<opinion>This is a pity, I like the syntax accepted by gcc much better, but as the wording of the standard doesn't make it explicit to allow this, the only safe bet is to assume it's forbidden, so clang is not to blame here...</opinion>

如果要引用 x bx bfx ,则可以使用这样的其他匿名联合:

If you want to refer to x by either b.x or b.f.x, you can use an additional anonymous union like this:

#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

这篇关于通过更高级别的结构访问子变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆