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


Groups > comp.lang.c > #4113

Re: Extending unions and ABI?

From Shao Miller <sha0.miller@gmail.com>
Newsgroups comp.lang.c
Subject Re: Extending unions and ABI?
Date 2011-05-16 15:43 -0400
Organization A noiseless patient Spider
Message-ID <iqrupp$21b$1@dont-email.me> (permalink)
References <yIdAp.1305$Wy2.200@newsfe23.ams2> <iqrqud$qdi$1@dont-email.me> <IqeAp.2489$ue1.1142@newsfe28.ams2>

Show all headers | View raw


On 5/16/2011 14:55, Jef Driesen wrote:
> On 16/05/11 20:38, Shao Miller wrote:
>> On 5/16/2011 14:06, Jef Driesen wrote:
>>> Suppose I have defined a union:
>>>
>>> typedef struct foo_t {
>>> ...
>>> } foo_t;
>>>
>>> typedef struct bar_t {
>>> ...
>>> } bar_t;
>>>
>>> typedef union foobar_t {
>>> foo_t foo;
>>> bar_t bar;
>>> } foobar_t;
>>>
>>> Which is part of the public api of my project.
>>
>> As in, these are in a header file and the struct and union definitions
>> will thus be available within all users' translation units, assuming
>> they include the header?
>
> Yes. How would they be able to use it otherwise?

I didn't (and don't) understand your "the union itself appears only in 
the implementation (e.g. in the dosomething() function)".  What about it 
only appears in the private TUs and not in the public headers?

[ Corrected typographical errors below.  Not sure why indenting dies 
with this news client.  Sorry. ]
>
>>> The union is used to pass
>>> different types of data (e.g. either a foo or a bar struct) back to the
>>> caller through a callback function. The type is used distinguish between
>>> the two:
>>>
>>> typedef enum foobar_type_t {
>>> FOO,
>>> BAR,
>>> } foobar_type_t;
>>>
>>> typedef void (*callback_t)(foobar_type_t type, const foobar_t *foobar);
>>>
>>> void
>>> dosomething (callback_t callback)
>>> {
>>>
>>> foobar_t foobar;
>>>
>>> foobar.foo = ...
>>> callback (FOO,&foobar);
>>>
>>> foobar.bar = ...
>>> callback (BAR,&foobar);
>>> }
>>>
>>> Note that I only use pointers to the union in the public api. The union
>>> itself appears only in the implementation (e.g. in the dosomething()
>>> function).
>>>
>>

The union definition?
---
   /* public.h */
   ...
   typedef union foobar_t foobar_t;
   ...
---
   /* private.c */
   ...
   typedef union foobar_t {
       foo_t foo;
       bar_t bar;
     } foobar_t;
   ...
---

Or is the definition in public.h?

>> Do you mean that the union definition you gave closer to the beginning
>> of your post is only within the translation unit with the
>> 'dosomething()' definition? Or do you mean that the only code which
>> will use the 'sizeof' or the members of the union will be within the
>> translation unit with the 'dosomething()' definition?
>
> The dosomething() function would be exposed in the public api, but the
> implementation would be internally to the library. A user would have to
> do something like this:
>
> #include <dosomething.h>
>
> void mycallback(foobar_type_t type, const foobar_t *foobar)
> {
> switch (type) {
> case FOO:
> /* Use foobar->foo.xyz */
> break;
> case BAR:
> /* Use foobar->bar.abc */
> break;
> }
> }
>
> int
> main (void)
> {
> dosomething (mycallback);
> }
>
> So the union is allocated in the dosomething() function in the library
> and passed back to the caller, not the other way around.

Looks good to me. :)

>
>>> Now suppose I need to extend my api to support a third type of data. Is
>>> it portable to just add a third struct to the union? Will it break the
>>> ABI rules and thus backwards compatibility. Is this a violation of the C
>>> standard?
>>>
>>
>> From n1256.pdf, section 6.2.5, point 27:
>>
>> "...All pointers to union types shall have the same representation
>> and alignment requirements as each other..."
>>
>> :)
>>
>>> The alternative would be to use a void pointer and require the user to
>>> cast to the appropriate data type,
>>
>> No need to cast a 'void *' to another pointer-to-object type.
>
> I know, but if it's not assigned to another variable, but converted
> on-the-fly like below I don't think you can avoid the cast.
>

Above, you have already shown:

   foobar->foo.xyz

So why cast?

[ Corrected typographical errors below. ]
>>> but this is less readable:
>>>
>>> foobar->foo.member
>>>
>>> vs
>>>
>>> ((foo_t *)foobar)->member
>>

Really?  I prefer the former, personally.

If you come up with version 2.0 of the "public.h" header and it includes 
a new structure in the union, that structure could affect the alignment 
requirements of the union.

If the only code that allocates such union objects is aware of the 
change, the alignment requirements should still satisfy the old union 
version, as long as you don't remove the old struct members, right?

I wouldn't expect that other users' code would care...  Their foos and 
bars are still aligned, and 'foo_t' and 'bar_t' still has the same tag 
and same definition[n1256.pdf:6.2.7p1].  I'd view the use of a "newer" 
union rather than the "outdated" union as "type-punning", under these 
circumstances.  I could be mistaken.

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Extending unions and ABI? Jef Driesen <jefdriesen@hotmail.com.invalid> - 2011-05-16 20:06 +0200
  Re: Extending unions and ABI? Tom St Denis <tom@iahu.ca> - 2011-05-16 11:20 -0700
    Re: Extending unions and ABI? jt@toerring.de (Jens Thoms Toerring) - 2011-05-16 19:12 +0000
  Re: Extending unions and ABI? Shao Miller <sha0.miller@gmail.com> - 2011-05-16 14:38 -0400
    Re: Extending unions and ABI? "Morris Keesan" <mkeesan@post.harvard.edu> - 2011-05-16 14:54 -0400
      Re: Extending unions and ABI? Shao Miller <sha0.miller@gmail.com> - 2011-05-16 15:13 -0400
    Re: Extending unions and ABI? Jef Driesen <jefdriesen@hotmail.com.invalid> - 2011-05-16 20:55 +0200
      Re: Extending unions and ABI? Shao Miller <sha0.miller@gmail.com> - 2011-05-16 15:43 -0400
        Re: Extending unions and ABI? Shao Miller <sha0.miller@gmail.com> - 2011-05-16 15:48 -0400
          Re: Extending unions and ABI? Jef Driesen <jefdriesen@hotmail.com.invalid> - 2011-05-17 20:10 +0200
            Re: Extending unions and ABI? Shao Miller <sha0.miller@gmail.com> - 2011-05-18 00:28 -0500
        Re: Extending unions and ABI? Jef Driesen <jefdriesen@hotmail.com.invalid> - 2011-05-16 21:54 +0200
  Re: Extending unions and ABI? Columbus sailed the ocean China Blue <chine.bleu@yahoo.com> - 2011-05-17 12:53 -0700
  Re: Extending unions and ABI? "io_x" <a@b.c.invalid> - 2011-05-18 19:31 +0200
  Re: Extending unions and ABI? gordonb.4d208@burditt.org (Gordon Burditt) - 2011-05-23 04:03 -0500
  Re: Extending unions and ABI? Tim Rentsch <txr@alumni.caltech.edu> - 2011-05-30 23:47 -0700

csiph-web