Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #158366 > unrolled thread

Anonymous unions

Started bySteve Keller <keller.steve@gmx.de>
First post2021-01-15 09:45 +0100
Last post2021-01-15 19:48 -0800
Articles 13 — 8 participants

Back to article view | Back to comp.lang.c


Contents

  Anonymous unions Steve Keller <keller.steve@gmx.de> - 2021-01-15 09:45 +0100
    Re: Anonymous unions "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-01-15 01:41 -0800
      Re: Anonymous unions Sumireko Usami <usasumi3hu@gmail.com> - 2021-01-15 13:00 +0100
        Re: Anonymous unions "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-01-16 14:04 -0800
      Re: Anonymous unions Bart <bc@freeuk.com> - 2021-01-15 12:38 +0000
        Re: Anonymous unions Bonita Montero <Bonita.Montero@gmail.com> - 2021-01-15 14:18 +0100
          Re: Anonymous unions Thiago Adams <thiago.adams@gmail.com> - 2021-01-15 06:37 -0800
            Re: Anonymous unions "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-01-16 14:05 -0800
              Re: Anonymous unions "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-01-16 14:08 -0800
            Re: Anonymous unions Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-01-16 19:04 -0800
              Re: Anonymous unions "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-01-16 19:32 -0800
    Re: Anonymous unions Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-01-15 10:10 -0800
    Re: Anonymous unions Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-01-15 19:48 -0800

#158366 — Anonymous unions

FromSteve Keller <keller.steve@gmx.de>
Date2021-01-15 09:45 +0100
SubjectAnonymous unions
Message-ID<rtrkml$1de$1@gioia.aioe.org>
I want to define something like the following:

    struct foo {
        int a;
	int b;
    };

    struct bar {
        ...;
	union {
	    int        a;
	    struct foo f;
	};
	...;
    };

Having a struct bar b, is it correct and that b.a and b.f.a is always
the same object?  I.e. will the following always work?

    struct bar b;
    struct foo f = { 42, 21 };
    b.f = f;
    if (b.a == 42)
        puts("worked");

I have tried with gcc and it works.  But does standard C guarantee this?

Steve

[toc] | [next] | [standalone]


#158368

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2021-01-15 01:41 -0800
Message-ID<rtro0d$19gs$2@gioia.aioe.org>
In reply to#158366
On 1/15/2021 12:45 AM, Steve Keller wrote:
> I want to define something like the following:
> 
>      struct foo {
>          int a;
> 	int b;
>      };
> 
>      struct bar {
>          ...;
> 	union {
> 	    int        a;
> 	    struct foo f;
> 	};
> 	...;
>      };


> 
> Having a struct bar b, is it correct and that b.a and b.f.a is always
> the same object?  I.e. will the following always work?
> 
>      struct bar b;
>      struct foo f = { 42, 21 };
>      b.f = f;
>      if (b.a == 42)
>          puts("worked");
> 
> I have tried with gcc and it works.  But does standard C guarantee this?

IIRC, anonymous unions are a gnu extension. But then again, they might 
be in C11. Need to check.

[toc] | [prev] | [next] | [standalone]


#158369

FromSumireko Usami <usasumi3hu@gmail.com>
Date2021-01-15 13:00 +0100
Message-ID<92fdca10-5bd8-18b3-065b-f26301c21418@gmail.com>
In reply to#158368
On 2021-01-15 10:41, Chris M. Thomasson wrote:
> On 1/15/2021 12:45 AM, Steve Keller wrote:
>> I want to define something like the following:
>>
>>      struct foo {
>>          int a;
>>     int b;
>>      };
>>
>>      struct bar {
>>          ...;
>>     union {
>>         int        a;
>>         struct foo f;
>>     };
>>     ...;
>>      };
> 
> 
>>
>> Having a struct bar b, is it correct and that b.a and b.f.a is always
>> the same object?  I.e. will the following always work?
>>
>>      struct bar b;
>>      struct foo f = { 42, 21 };
>>      b.f = f;
>>      if (b.a == 42)
>>          puts("worked");
>>
>> I have tried with gcc and it works.  But does standard C guarantee this?
> 
> IIRC, anonymous unions are a gnu extension. But then again, they might 
> be in C11. Need to check.
> 

Seems that anonymous unions are in C11.
https://en.cppreference.com/w/c/language/union#Explanation

[toc] | [prev] | [next] | [standalone]


#158399

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2021-01-16 14:04 -0800
Message-ID<rtvnt8$v2$1@gioia.aioe.org>
In reply to#158369
On 1/15/2021 4:00 AM, Sumireko Usami wrote:
> On 2021-01-15 10:41, Chris M. Thomasson wrote:
>> On 1/15/2021 12:45 AM, Steve Keller wrote:
>>> I want to define something like the following:
>>>
>>>      struct foo {
>>>          int a;
>>>     int b;
>>>      };
>>>
>>>      struct bar {
>>>          ...;
>>>     union {
>>>         int        a;
>>>         struct foo f;
>>>     };
>>>     ...;
>>>      };
>>
>>
>>>
>>> Having a struct bar b, is it correct and that b.a and b.f.a is always
>>> the same object?  I.e. will the following always work?
>>>
>>>      struct bar b;
>>>      struct foo f = { 42, 21 };
>>>      b.f = f;
>>>      if (b.a == 42)
>>>          puts("worked");
>>>
>>> I have tried with gcc and it works.  But does standard C guarantee this?
>>
>> IIRC, anonymous unions are a gnu extension. But then again, they might 
>> be in C11. Need to check.
>>
> 
> Seems that anonymous unions are in C11.
> https://en.cppreference.com/w/c/language/union#Explanation

Indeed they are.

[toc] | [prev] | [next] | [standalone]


#158370

FromBart <bc@freeuk.com>
Date2021-01-15 12:38 +0000
Message-ID<i1gMH.873535$b5kb.224574@fx15.ams4>
In reply to#158368
On 15/01/2021 09:41, Chris M. Thomasson wrote:
> On 1/15/2021 12:45 AM, Steve Keller wrote:
>> I want to define something like the following:
>>
>>      struct foo {
>>          int a;
>>     int b;
>>      };
>>
>>      struct bar {
>>          ...;
>>     union {
>>         int        a;
>>         struct foo f;
>>     };
>>     ...;
>>      };
> 
> 
>>
>> Having a struct bar b, is it correct and that b.a and b.f.a is always
>> the same object?  I.e. will the following always work?
>>
>>      struct bar b;
>>      struct foo f = { 42, 21 };
>>      b.f = f;
>>      if (b.a == 42)
>>          puts("worked");
>>
>> I have tried with gcc and it works.  But does standard C guarantee this?
> 
> IIRC, anonymous unions are a gnu extension. But then again, they might 
> be in C11. Need to check.
> 

They have worked for every compiler I've used for probably 20 years. 
Probably C11 makes them official, if not C99.

[toc] | [prev] | [next] | [standalone]


#158371

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-01-15 14:18 +0100
Message-ID<rts4li$cp0$1@dont-email.me>
In reply to#158370
> They have worked for every compiler I've used for probably 20 years. 
> Probably C11 makes them official, if not C99.

Yes, they exist since C11:
https://en.cppreference.com/w/c/language/union#Explanation
But I'm sure the behaviour is implementation-defined if you use them
for aliasing-purposes.

[toc] | [prev] | [next] | [standalone]


#158373

FromThiago Adams <thiago.adams@gmail.com>
Date2021-01-15 06:37 -0800
Message-ID<cae3c3da-9997-4984-9f10-0eff6908ce02n@googlegroups.com>
In reply to#158371
On Friday, January 15, 2021 at 10:17:51 AM UTC-3, Bonita Montero wrote:
> > They have worked for every compiler I've used for probably 20 years. 
> > Probably C11 makes them official, if not C99.
> Yes, they exist since C11: 
> https://en.cppreference.com/w/c/language/union#Explanation 
> But I'm sure the behaviour is implementation-defined if you use them 
> for aliasing-purposes.


Just for curiosity, Microsoft compiler has an extension that 
injects one struct on another. They are unnamed members.

struct point2d {  int x,y; };
struct point3d {  struct point2d;  int z;   };

int main(){
  struct point3d pt = {.x=1, .y=2 , .z=3};
}

[toc] | [prev] | [next] | [standalone]


#158400

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2021-01-16 14:05 -0800
Message-ID<rtvnut$v2$2@gioia.aioe.org>
In reply to#158373
On 1/15/2021 6:37 AM, Thiago Adams wrote:
> On Friday, January 15, 2021 at 10:17:51 AM UTC-3, Bonita Montero wrote:
>>> They have worked for every compiler I've used for probably 20 years.
>>> Probably C11 makes them official, if not C99.
>> Yes, they exist since C11:
>> https://en.cppreference.com/w/c/language/union#Explanation
>> But I'm sure the behaviour is implementation-defined if you use them
>> for aliasing-purposes.
> 
> 
> Just for curiosity, Microsoft compiler has an extension that
> injects one struct on another. They are unnamed members.
> 
> struct point2d {  int x,y; };
> struct point3d {  struct point2d;  int z;   };
> 
> int main(){
>    struct point3d pt = {.x=1, .y=2 , .z=3};
> }
> 


Interesting. Never tried it out.

[toc] | [prev] | [next] | [standalone]


#158402

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2021-01-16 14:08 -0800
Message-ID<rtvo50$5cf$1@gioia.aioe.org>
In reply to#158400
On 1/16/2021 2:05 PM, Chris M. Thomasson wrote:
> On 1/15/2021 6:37 AM, Thiago Adams wrote:
>> On Friday, January 15, 2021 at 10:17:51 AM UTC-3, Bonita Montero wrote:
>>>> They have worked for every compiler I've used for probably 20 years.
>>>> Probably C11 makes them official, if not C99.
>>> Yes, they exist since C11:
>>> https://en.cppreference.com/w/c/language/union#Explanation
>>> But I'm sure the behaviour is implementation-defined if you use them
>>> for aliasing-purposes.
>>
>>
>> Just for curiosity, Microsoft compiler has an extension that
>> injects one struct on another. They are unnamed members.
>>
>> struct point2d {  int x,y; };
>> struct point3d {  struct point2d;  int z;   };
>>
>> int main(){
>>    struct point3d pt = {.x=1, .y=2 , .z=3};
>> }
>>
> 
> 
> Interesting. Never tried it out.

I am assuming that the names of the struct members need to be unique? x, 
y, z works well here. So would p0, p1, p2, ... as individual component 
parts of a point.

[toc] | [prev] | [next] | [standalone]


#158404

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2021-01-16 19:04 -0800
Message-ID<ru09gn$ivd$1@dont-email.me>
In reply to#158373
On 1/15/2021 6:37 AM, Thiago Adams wrote:
> 
> Just for curiosity, Microsoft compiler has an extension that
> injects one struct on another. They are unnamed members.
> 
> struct point2d {  int x,y; };
> struct point3d {  struct point2d;  int z;   };
> 
> int main(){
>    struct point3d pt = {.x=1, .y=2 , .z=3};
> }
> 

The idea of that extension is to simplify implementing "inheritance" in 
C. It is also available in GCC and Clang under `-fms-extensions`.

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [next] | [standalone]


#158405

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2021-01-16 19:32 -0800
Message-ID<ru0b51$5c1$1@gioia.aioe.org>
In reply to#158404
On 1/16/2021 7:04 PM, Andrey Tarasevich wrote:
> On 1/15/2021 6:37 AM, Thiago Adams wrote:
>>
>> Just for curiosity, Microsoft compiler has an extension that
>> injects one struct on another. They are unnamed members.
>>
>> struct point2d {  int x,y; };
>> struct point3d {  struct point2d;  int z;   };
>>
>> int main(){
>>    struct point3d pt = {.x=1, .y=2 , .z=3};
>> }
>>
> 
> The idea of that extension is to simplify implementing "inheritance" in 
> C. It is also available in GCC and Clang under `-fms-extensions`.
> 

Nice info. Thanks Andrey.

[toc] | [prev] | [next] | [standalone]


#158376

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-01-15 10:10 -0800
Message-ID<86zh1anka3.fsf@linuxsc.com>
In reply to#158366
Steve Keller <keller.steve@gmx.de> writes:

> I want to define something like the following:
>
>     struct foo {
>         int a;
>     int b;
>     };
>
>     struct bar {
>         ...;
>     union {
>         int        a;
>         struct foo f;
>     };
>     ...;
>     };
>
> Having a struct bar b, is it correct and that b.a and b.f.a is
> always the same object?  I.e. will the following always work?
>
>     struct bar b;
>     struct foo f = { 42, 21 };
>     b.f = f;
>     if (b.a == 42)
>         puts("worked");
>
> I have tried with gcc and it works.  But does standard C guarantee
> this?

The short answer is yes.

A somewhat longer answer would say that anonymous unions have been
supported in standard C only since C11.

Also, technically the objects b.a and b.f.a are distinct objects,
but they are required to occupy the same area of memory, which is
(part of) what I think you're asking.

Furthermore the read access to b.a is well defined, and required
to work as you expect after the store into b.f.  (It is not, as
some may have suggested, implementation-defined behavior.)

Having said that, I might suggest some amount of caution is in
order, because the case is unusual enough so some compilers may
get it wrong.  I know that isn't what you are asking, and it may
turn out not to be a problem at all, but it is something that you
may want to take into consideration.  Disclaimer:  I have no
actual experience with something like this being a problem, and
I would expect any major compiler such as gcc or clang always to
act as you expect.  Despite that, a word to the wise seemed in
order.

[toc] | [prev] | [next] | [standalone]


#158392

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2021-01-15 19:48 -0800
Message-ID<rttnm3$7m5$1@dont-email.me>
In reply to#158366
On 1/15/2021 12:45 AM, Steve Keller wrote:
> I want to define something like the following:
> 
>      struct foo {
>          int a;
> 	int b;
>      };
> 
>      struct bar {
>          ...;
> 	union {
> 	    int        a;
> 	    struct foo f;
> 	};
> 	...;
>      };
> 
> Having a struct bar b, is it correct and that b.a and b.f.a is always
> the same object?  I.e. will the following always work?
> 
>      struct bar b;
>      struct foo f = { 42, 21 };
>      b.f = f;
>      if (b.a == 42)
>          puts("worked");
> 
> I have tried with gcc and it works.  But does standard C guarantee this?

Depends on what you mean by "this". There are two different matters 
involved here:

1. The legality of the "anonymous" declaration.

   Anonymous struct/union declarations (no tag, no member declared) are 
legal since C11 for both struct and union declarations. Note the "no 
tag" requirement. Once your struct/union has a tag the "classic" rules 
kick in: you will not be able to declare it inside another struct/union 
without declaring a named member of that type.

2. The guarantees about mutual "alignment" of overlapping union members.

   In your particular case (i.e. accessing the first `int` member of the 
inner struct vs. accessing an adjacent `int` in the same union) you are 
safe.

-- 
Best regards,
Andrey Tarasevich

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web