Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
355 views
in Technique[技术] by (71.8m points)

Are C-structs with the same members types guaranteed to have the same layout in memory?

Essentially, if I have

typedef struct {
    int x;
    int y;
} A;

typedef struct {
    int h;
    int k;
} B;

and I have A a, does the C standard guarantee that ((B*)&a)->k is the same as a.y?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Are C-structs with the same members types guaranteed to have the same layout in memory?

Almost yes. Close enough for me.

From n1516, Section 6.5.2.3, paragraph 6:

... if a union contains several structures that share a common initial sequence ..., 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.

This means that if you have the following code:

struct a {
    int x;
    int y;
};

struct b {
    int h;
    int k;
};

union {
    struct a a;
    struct b b;
} u;

If you assign to u.a, the standard says that you can read the corresponding values from u.b. It stretches the bounds of plausibility to suggest that struct a and struct b can have different layout, given this requirement. Such a system would be pathological in the extreme.

Remember that the standard also guarantees that:

  • Structures are never trap representations.

  • Addresses of fields in a structure increase (a.x is always before a.y).

  • The offset of the first field is always zero.

However, and this is important!

You rephrased the question,

does the C standard guarantee that ((B*)&a)->k is the same as a.y?

No! And it very explicitly states that they are not the same!

struct a { int x; };
struct b { int x; };
int test(int value)
{
    struct a a;
    a.x = value;
    return ((struct b *) &a)->x;
}

This is an aliasing violation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...