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


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

Struct and Union

Started byjanus <emekamicro@gmail.com>
First post2015-07-10 00:49 -0700
Last post2015-07-10 19:12 -0700
Articles 20 on this page of 33 — 13 participants

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


Contents

  Struct and Union janus <emekamicro@gmail.com> - 2015-07-10 00:49 -0700
    Re: Struct and Union Richard Heathfield <rjh@cpax.org.uk> - 2015-07-10 09:04 +0100
      Re: Struct and Union janus <emekamicro@gmail.com> - 2015-07-10 01:40 -0700
        Re: Struct and Union Richard Heathfield <rjh@cpax.org.uk> - 2015-07-10 09:50 +0100
          Re: Struct and Union Richard Heathfield <rjh@cpax.org.uk> - 2015-07-10 13:44 +0100
      Re: Struct and Union "Bill Davy" <Bill@SynectixLtd.com> - 2015-07-10 12:37 +0100
        Re: Struct and Union Keith Thompson <kst-u@mib.org> - 2015-07-10 08:24 -0700
          Re: Struct and Union Keith Thompson <kst-u@mib.org> - 2015-07-12 12:53 -0700
    Re: Struct and Union Ian Collins <ian-news@hotmail.com> - 2015-07-10 21:32 +1200
    Re: Struct and Union "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-10 05:12 -0700
      Re: Struct and Union Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-10 17:35 +0100
        Re: Struct and Union David Kleinecke <dkleinecke@gmail.com> - 2015-07-10 10:18 -0700
          Re: Struct and Union "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-10 10:23 -0700
          Re: Struct and Union James Kuyper <jameskuyper@verizon.net> - 2015-07-10 13:47 -0400
          Re: Struct and Union Keith Thompson <kst-u@mib.org> - 2015-07-10 12:38 -0700
        Re: Struct and Union "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-10 10:27 -0700
    Re: Struct and Union Bartc <bc@freeuk.com> - 2015-07-10 13:55 +0100
    Re: Struct and Union Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-10 21:48 +0100
      Re: Struct and Union "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-10 13:51 -0700
        Re: Struct and Union Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-10 23:45 +0100
          Re: Struct and Union "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-10 17:43 -0700
            Re: Struct and Union Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-11 13:04 +0100
              Re: Struct and Union "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-11 05:15 -0700
                Re: Struct and Union Bartc <bc@freeuk.com> - 2015-07-11 14:01 +0100
                  Re: Struct and Union "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-11 06:05 -0700
                    Re: Struct and Union "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-11 06:13 -0700
              Re: Struct and Union Keith Thompson <kst-u@mib.org> - 2015-07-11 13:51 -0700
                Re: Struct and Union Martin Shobe <martin.shobe@yahoo.com> - 2015-07-11 16:51 -0500
                Re: Struct and Union Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-11 23:13 +0100
                  Re: Struct and Union Keith Thompson <kst-u@mib.org> - 2015-07-11 17:39 -0700
                Re: Struct and Union Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-11 16:56 -0700
    Re: Struct and Union Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-10 18:52 -0700
    Re: Struct and Union Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-10 19:12 -0700

Page 1 of 2  [1] 2  Next page →


#65093 — Struct and Union

Fromjanus <emekamicro@gmail.com>
Date2015-07-10 00:49 -0700
SubjectStruct and Union
Message-ID<a653fc98-5fae-48ff-ba1c-d7b53adee150@googlegroups.com>
Hello All,

I have 2 options but which one is idiomatic C?

1)
typedef struct CStatement
{
    int stype;

    union Statement
    {
        CPrintStatement* printstatement;
        CInputStatement* inputstatement;
        CAssignStatement* assignstatement;
        CGotoStatement* gotostatement;
        CIfThenStatement* ifthenstatement;
        void* sstatement;

    } statement;
}CStatement;


2)
typedef struct CStatement
{
    int stype;

    void* sstatement;

}CStatement;


Regards, \Emeka

[toc] | [next] | [standalone]


#65094

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-07-10 09:04 +0100
Message-ID<mnnu72$59k$1@dont-email.me>
In reply to#65093
On 10/07/15 08:49, janus wrote:
> Hello All,
>
> I have 2 options but which one is idiomatic C?
>
> 1)
> typedef struct CStatement
> {
>      int stype;
>
>      union Statement
>      {
>          CPrintStatement* printstatement;
>          CInputStatement* inputstatement;
>          CAssignStatement* assignstatement;
>          CGotoStatement* gotostatement;
>          CIfThenStatement* ifthenstatement;
>          void* sstatement;
>
>      } statement;
> }CStatement;
>
>
> 2)
> typedef struct CStatement
> {
>      int stype;
>
>      void* sstatement;
>
> }CStatement;
>


To get your actual question out of the way, I would argue that the 
second is idiomatic C, whereas the first looks inelegant and crufty.

If it weren't for your catch-all void * in the first one, I'd say it was 
marginally safer, in that adding an extra type in one part of the code 
and forgetting to support it everywhere else is more likely to bite you 
at compile time rather than at runtime (which is a Good Thing), but the 
catch-all void * somewhat diminishes that advantage.

Which would I choose? The second one, without question. But I'd tread 
carefully.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

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


#65095

Fromjanus <emekamicro@gmail.com>
Date2015-07-10 01:40 -0700
Message-ID<d869b162-7a7e-46c5-a1e8-64c811c1393c@googlegroups.com>
In reply to#65094
On Friday, July 10, 2015 at 9:04:22 AM UTC+1, Richard Heathfield wrote:
> On 10/07/15 08:49, janus wrote:
> > Hello All,
> >
> > I have 2 options but which one is idiomatic C?
> >
> > 1)
> > typedef struct CStatement
> > {
> >      int stype;
> >
> >      union Statement
> >      {
> >          CPrintStatement* printstatement;
> >          CInputStatement* inputstatement;
> >          CAssignStatement* assignstatement;
> >          CGotoStatement* gotostatement;
> >          CIfThenStatement* ifthenstatement;
> >          void* sstatement;
> >
> >      } statement;
> > }CStatement;
> >
> >
> > 2)
> > typedef struct CStatement
> > {
> >      int stype;
> >
> >      void* sstatement;
> >
> > }CStatement;
> >
> 
> 
> To get your actual question out of the way, I would argue that the 
> second is idiomatic C, whereas the first looks inelegant and crufty.
> 
> If it weren't for your catch-all void * in the first one, I'd say it was 
> marginally safer, in that adding an extra type in one part of the code 
> and forgetting to support it everywhere else is more likely to bite you 
> at compile time rather than at runtime (which is a Good Thing), but the 
> catch-all void * somewhat diminishes that advantage.
> 
> Which would I choose? The second one, without question. But I'd tread 
> carefully.
> 
> -- 
> Richard Heathfield
> Email: rjh at cpax dot org dot uk
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line 4 vacant - apply within


typedef struct CStatement 
{ 
    int stype; 

    union Statement 
    { 
        CPrintStatement* printstatement; 
        CInputStatement* inputstatement; 
        CAssignStatement* assignstatement; 
        CGotoStatement* gotostatement; 
        CIfThenStatement* ifthenstatement; 
        //void* sstatement; 

    } statement; 
}CStatement; 


2) 
typedef struct CStatement 
{ 
    int stype; 

    void* sstatement; 

}CStatement; 


I noticed a typo, if I comment out void * inside option 1, would your decision change?

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


#65096

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-07-10 09:50 +0100
Message-ID<mno0uo$du0$1@dont-email.me>
In reply to#65095
On 10/07/15 09:40, janus wrote:

<snip>

> I noticed a typo, if I comment out void * inside option 1, would your decision change?

No.

void * is not for the faint-hearted, but this is absolutely the kind of 
thing it's designed for, and I would not hesitate in using it. As I said 
earlier, there /are/ advantages to the first method, but the sheer 
clumsiness of it is something I would seek to avoid.

You should bear in mind when assessing this response that:

* either decision can certainly work, and work well;
* when I comment on matters of preference, I often find myself to be in 
a minority.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

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


#65108

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-07-10 13:44 +0100
Message-ID<mnoek8$rdt$1@dont-email.me>
In reply to#65096
On 10/07/15 13:32, Stefan Ram wrote:
> Richard Heathfield <rjh@cpax.org.uk> writes:
>>void * is not for the faint-hearted, but this is absolutely the kind of
>
>    The OP wants to handle run-time types. He should take care
>    not to reinvent OOP. What he wants to implement possibly is
>    what »C with classes« was made for. He should check out C++
>    for it.


When I first looked at his code, "C++" did kind of shout itself out at 
me, but I figured that he was asking in clc for a reason.

You're right, though - he may wish to reconsider whether C++ might be a 
more appropriate language for this task.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

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


#65101

From"Bill Davy" <Bill@SynectixLtd.com>
Date2015-07-10 12:37 +0100
Message-ID<d09p4cFjht7U1@mid.individual.net>
In reply to#65094
"Richard Heathfield" <rjh@cpax.org.uk> wrote in message 
news:mnnu72$59k$1@dont-email.me...
> On 10/07/15 08:49, janus wrote:
>> Hello All,
>>
>> I have 2 options but which one is idiomatic C?
>>
>> 1)
>> typedef struct CStatement
>> {
>>      int stype;
>>
>>      union Statement
>>      {
>>          CPrintStatement* printstatement;
>>          CInputStatement* inputstatement;
>>          CAssignStatement* assignstatement;
>>          CGotoStatement* gotostatement;
>>          CIfThenStatement* ifthenstatement;
>>          void* sstatement;
>>
>>      } statement;
>> }CStatement;
>>
>>
>> 2)
>> typedef struct CStatement
>> {
>>      int stype;
>>
>>      void* sstatement;
>>
>> }CStatement;
>>
>
>
> To get your actual question out of the way, I would argue that the second 
> is idiomatic C, whereas the first looks inelegant and crufty.
>
> If it weren't for your catch-all void * in the first one, I'd say it was 
> marginally safer, in that adding an extra type in one part of the code and 
> forgetting to support it everywhere else is more likely to bite you at 
> compile time rather than at runtime (which is a Good Thing), but the 
> catch-all void * somewhat diminishes that advantage.
>
> Which would I choose? The second one, without question. But I'd tread 
> carefully.
>
> -- 
> Richard Heathfield
> Email: rjh at cpax dot org dot uk
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line 4 vaca

Is enum part of C?  If so, I'd prefer enum {tPrint=1, tInput, tGoto, etc} 
stype (or whatever the syntax is).

This makes it easier for a compiler (or checker like PC-Lint) to see if a 
switch on stype is missing a value, which is useful when the list changes 
later.  Avoiding the enumeration value zero also slightly improves your odds 
in that a null initialised stype is incorrect. 

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


#65116

FromKeith Thompson <kst-u@mib.org>
Date2015-07-10 08:24 -0700
Message-ID<ln8uao8286.fsf@kst-u.example.com>
In reply to#65101
"Bill Davy" <Bill@SynectixLtd.com> writes:
[...]
> Is enum part of C?

Certainly.

>                     If so, I'd prefer enum {tPrint=1, tInput, tGoto, etc} 
> stype (or whatever the syntax is).

I agree.

> This makes it easier for a compiler (or checker like PC-Lint) to see if a 
> switch on stype is missing a value, which is useful when the list changes 
> later.  Avoiding the enumeration value zero also slightly improves your odds 
> in that a null initialised stype is incorrect. 

C enums are basically integers with a light sprinkling of syntactic
sugar.  Compilers, as far as I know, don't typically don't warn about
missing values in switch statements; they certainly aren't required to
do so.

Lint-like tools may or may not perform such checks.  (I don't know
whether PC-Lint does or not; it's not cheap, and it's Windows only.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#65445

FromKeith Thompson <kst-u@mib.org>
Date2015-07-12 12:53 -0700
Message-ID<lnh9p9m9t7.fsf@kst-u.example.com>
In reply to#65116
Keith Thompson <kst-u@mib.org> writes:
> "Bill Davy" <Bill@SynectixLtd.com> writes:
> [...]
>> Is enum part of C?
>
> Certainly.
>
>>                     If so, I'd prefer enum {tPrint=1, tInput, tGoto, etc} 
>> stype (or whatever the syntax is).
>
> I agree.
>
>> This makes it easier for a compiler (or checker like PC-Lint) to see
>> if a switch on stype is missing a value, which is useful when the
>> list changes later.  Avoiding the enumeration value zero also
>> slightly improves your odds in that a null initialised stype is
>> incorrect.
>
> C enums are basically integers with a light sprinkling of syntactic
> sugar.  Compilers, as far as I know, don't typically don't warn about
> missing values in switch statements; they certainly aren't required to
> do so.

My mistake.  gcc has an option "-Wswitch" (which is also enabled by
"-Wall") to issue such warnings.  clang has the same option.  I don't
know about other compilers.

> Lint-like tools may or may not perform such checks.  (I don't know
> whether PC-Lint does or not; it's not cheap, and it's Windows only.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#65097

FromIan Collins <ian-news@hotmail.com>
Date2015-07-10 21:32 +1200
Message-ID<d09hpqFegarU1@mid.individual.net>
In reply to#65093
janus wrote:
> Hello All,
>
> I have 2 options but which one is idiomatic C?
>
> 1)
> typedef struct CStatement
> {
>      int stype;
>
>      union Statement
>      {
>          CPrintStatement* printstatement;
>          CInputStatement* inputstatement;
>          CAssignStatement* assignstatement;
>          CGotoStatement* gotostatement;
>          CIfThenStatement* ifthenstatement;
>          void* sstatement;
>
>      } statement;
> }CStatement;
>

How about

typedef struct Statement
{
     int type;

     union
     {
         PrintStatement  printstatement;
         InputStatement  inputstatement;
         AssignStatement assignstatement;
         GotoStatement   gotostatement;
         IfThenStatement ifthenstatement;
     } statement;

} Statement;

(I didn't see any point in the Cs)

-- 
Ian Collins

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


#65104

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-10 05:12 -0700
Message-ID<405a385f-f728-45c0-adfa-c6e1a1662938@googlegroups.com>
In reply to#65093
On Friday, July 10, 2015 at 3:49:56 AM UTC-4, janus wrote:
> Hello All,
> 
> I have 2 options but which one is idiomatic C?
> 
> 1)
> typedef struct CStatement
> {
>     int stype;
> 
>     union Statement
>     {
>         CPrintStatement* printstatement;
>         CInputStatement* inputstatement;
>         CAssignStatement* assignstatement;
>         CGotoStatement* gotostatement;
>         CIfThenStatement* ifthenstatement;
>         void* sstatement;
> 
>     } statement;
> }CStatement;

I would go with this one.  In your debugger, you can use each of those
pointer types to access members directly.

I would also make it an unnamed union, that way you don't have:
    myCStatementPtr->statement.inputstatement = ...;

Seems like a lot of "statements".  You could just have:
    myCStatementPtr->inputstatement = ...;

I use something similar in a language I'm developing.  See this code
on GitHub around line 403:

    https://github.com/RickCHodgin/libsf/blob/master/source/vjr/source/vjr_structs0.h

Simplified:

    struct SVariable
    {
        // Variable content based on type
        u32     varType;

        union {
            SObject*        obj;
            SFunction*      thisCode;
            SBitmap*        bmp;
            SField*         field;
            SDatum          value;
        };
    };

Best regards,
Rick C. Hodgin

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


#65134

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-07-10 17:35 +0100
Message-ID<87oajkvukx.fsf@bsb.me.uk>
In reply to#65104
"Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:

> On Friday, July 10, 2015 at 3:49:56 AM UTC-4, janus wrote:
>> Hello All,
>> 
>> I have 2 options but which one is idiomatic C?
>> 
>> 1)
>> typedef struct CStatement
>> {
>>     int stype;
>> 
>>     union Statement
>>     {
>>         CPrintStatement* printstatement;
>>         CInputStatement* inputstatement;
>>         CAssignStatement* assignstatement;
>>         CGotoStatement* gotostatement;
>>         CIfThenStatement* ifthenstatement;
>>         void* sstatement;
>> 
>>     } statement;
>> }CStatement;
>
> I would go with this one.  In your debugger, you can use each of those
> pointer types to access members directly.
>
> I would also make it an unnamed union, that way you don't have:
>     myCStatementPtr->statement.inputstatement = ...;

But note that that is a new feature in C2011.  It was, I think, widely
implemented before that, but if the OP wants to write the most portable
C it should be avoided.

> Seems like a lot of "statements".  You could just have:
>     myCStatementPtr->inputstatement = ...;
>
> I use something similar in a language I'm developing.  See this code
> on GitHub around line 403:
>
>     https://github.com/RickCHodgin/libsf/blob/master/source/vjr/source/vjr_structs0.h

And everyone should note that you don't write C but C++ (that file in
C++ code), so your choices *may* be different to those of a C
programmer.

<snip>
-- 
Ben.

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


#65142

FromDavid Kleinecke <dkleinecke@gmail.com>
Date2015-07-10 10:18 -0700
Message-ID<44898eb2-560d-444f-bea4-1ddf7bb69f36@googlegroups.com>
In reply to#65134
On Friday, July 10, 2015 at 9:36:07 AM UTC-7, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:
> 
> > On Friday, July 10, 2015 at 3:49:56 AM UTC-4, janus wrote:
> >> Hello All,
> >> 
> >> I have 2 options but which one is idiomatic C?
> >> 
> >> 1)
> >> typedef struct CStatement
> >> {
> >>     int stype;
> >> 
> >>     union Statement
> >>     {
> >>         CPrintStatement* printstatement;
> >>         CInputStatement* inputstatement;
> >>         CAssignStatement* assignstatement;
> >>         CGotoStatement* gotostatement;
> >>         CIfThenStatement* ifthenstatement;
> >>         void* sstatement;
> >> 
> >>     } statement;
> >> }CStatement;
> >

The real reason for using a union is if the members are of different
sized types and you want to insure that all of them fit. All pointers
are the same size so a union is inappropriate here.

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


#65144

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-10 10:23 -0700
Message-ID<43b408e0-1ae2-44cf-b628-3d4cf9a8a0f2@googlegroups.com>
In reply to#65142
On Friday, July 10, 2015 at 1:18:23 PM UTC-4, David Kleinecke wrote:
> On Friday, July 10, 2015 at 9:36:07 AM UTC-7, Ben Bacarisse wrote:
> > "Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:
> > 
> > > On Friday, July 10, 2015 at 3:49:56 AM UTC-4, janus wrote:
> > >> Hello All,
> > >> 
> > >> I have 2 options but which one is idiomatic C?
> > >> 
> > >> 1)
> > >> typedef struct CStatement
> > >> {
> > >>     int stype;
> > >> 
> > >>     union Statement
> > >>     {
> > >>         CPrintStatement* printstatement;
> > >>         CInputStatement* inputstatement;
> > >>         CAssignStatement* assignstatement;
> > >>         CGotoStatement* gotostatement;
> > >>         CIfThenStatement* ifthenstatement;
> > >>         void* sstatement;
> > >> 
> > >>     } statement;
> > >> }CStatement;
> > >
> 
> The real reason for using a union is if the members are of different
> sized types and you want to insure that all of them fit. All pointers
> are the same size so a union is inappropriate here.

I disagree.  The reason a union *IS* appropriate here is because each
of the union types will be used based on the other struct member's
value.  When 1 it will be printstatement, when 2 inputstatement, etc.
But, it will never be more than one of them at a time, and so they
can occupy the same space because it is appropriate to do so.

And in my case (the SVariable structure), the types can change at any
time based on a setting.

In my VXB (XBASE-like) syntax:

    LOCAL v       && define the variable to exist

    v = 5         && now it's an integer
    v = "rick"    && now it's a "character" variable, a string

Best regards,
Rick C. Hodgin

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


#65150

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-07-10 13:47 -0400
Message-ID<55A0052E.5030904@verizon.net>
In reply to#65142
On 07/10/2015 01:18 PM, David Kleinecke wrote:
> On Friday, July 10, 2015 at 9:36:07 AM UTC-7, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:
>>
>>> On Friday, July 10, 2015 at 3:49:56 AM UTC-4, janus wrote:
>>>> Hello All,
>>>>
>>>> I have 2 options but which one is idiomatic C?
>>>>
>>>> 1)
>>>> typedef struct CStatement
>>>> {
>>>>     int stype;
>>>>
>>>>     union Statement
>>>>     {
>>>>         CPrintStatement* printstatement;
>>>>         CInputStatement* inputstatement;
>>>>         CAssignStatement* assignstatement;
>>>>         CGotoStatement* gotostatement;
>>>>         CIfThenStatement* ifthenstatement;
>>>>         void* sstatement;
>>>>
>>>>     } statement;
>>>> }CStatement;
>>>
> 
> The real reason for using a union is if the members are of different
> sized types and you want to insure that all of them fit.

That's one reason to use unions. It has the disadvantage that it takes
up the same amount of space as the largest member type, which can be
wasteful if most uses of the union use a type that's much smaller than
the largest.
However, type punning is also a common use of unions, and that's
precisely what's going on here. The actual memory being pointed at by
those pointers might (or might not) be dynamically allocated.

> ... All pointers are the same size ...

That's not true in general. It might be true if all of those typedefs
are for struct types, or for [[un]signed] char*. Otherwise, you can't be
sure whether they all have the same size except by testing. The results
of the test using one compiler might be different than when using a
different compiler - and that's the case even if both compilers are
targeting the same platform.

> ... so a union is inappropriate here.

For type punning, having all of the members of a union being at least
approximately the same size makes the union more space efficient.

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


#65182

FromKeith Thompson <kst-u@mib.org>
Date2015-07-10 12:38 -0700
Message-ID<lntwtbrefh.fsf@kst-u.example.com>
In reply to#65142
David Kleinecke <dkleinecke@gmail.com> writes:
> On Friday, July 10, 2015 at 9:36:07 AM UTC-7, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:
>> > On Friday, July 10, 2015 at 3:49:56 AM UTC-4, janus wrote:
>> >> I have 2 options but which one is idiomatic C?
>> >> 
>> >> 1)
>> >> typedef struct CStatement
>> >> {
>> >>     int stype;
>> >> 
>> >>     union Statement
>> >>     {
>> >>         CPrintStatement* printstatement;
>> >>         CInputStatement* inputstatement;
>> >>         CAssignStatement* assignstatement;
>> >>         CGotoStatement* gotostatement;
>> >>         CIfThenStatement* ifthenstatement;
>> >>         void* sstatement;
>> >> 
>> >>     } statement;
>> >> }CStatement;
>
> The real reason for using a union is if the members are of different
> sized types and you want to insure that all of them fit.

That's not the only reason.  A union exposes the fact that only one of
the members is valid at any time.  (You need other information, in this
case `stype`, to keep track of which one is currently valid.)  Using a
union rather than a structure saves some space (not a lot in this case),
but that space saving is not the only reason to use a union.

>                                                          All pointers
> are the same size so a union is inappropriate here.

All pointers are *not* necessarily the same size.  And even if they are
for a given implementation (which is common), that wouldn't be a good
argument against using a union; the pointers are of different *types*,
even if they have exactly the same representation.

Given that they're pointers, using a single void* is also a reasonable
approach.  Again we don't necessarily know (and needn't care) whether
void* and CPrintStatement* are the same size.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#65145

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-10 10:27 -0700
Message-ID<9bc8aeef-6175-4008-8363-94475a1f58e6@googlegroups.com>
In reply to#65134
On Friday, July 10, 2015 at 12:36:07 PM UTC-4, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:
> > https://github.com/RickCHodgin/libsf/blob/master/source/vjr/source/vjr_structs0.h
> 
> And everyone should note that you don't write C but C++ (that file in
> C++ code), so your choices *may* be different to those of a C
> programmer.

Technically I write in the form of C I'd like to see, which would be
mostly C with a few C++ features thrown in.  I would like to include
the class, but I do not do so presently because I do want to stick
closer to C for use with future C compilers (until RDC is completed,
Lord willing -- James 4:15 "For that ye ought to say, If the Lord
will, we shall live, and do this, or that").

Best regards,
Rick C. Hodgin

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


#65109

FromBartc <bc@freeuk.com>
Date2015-07-10 13:55 +0100
Message-ID<mnof9b$u18$1@dont-email.me>
In reply to#65093
On 10/07/2015 08:49, janus wrote:
> Hello All,
>
> I have 2 options but which one is idiomatic C?
>
> 1)
> typedef struct CStatement
> {
>      int stype;
>
>      union Statement
>      {
>          CPrintStatement* printstatement;
>          CInputStatement* inputstatement;
>          CAssignStatement* assignstatement;
>          CGotoStatement* gotostatement;
>          CIfThenStatement* ifthenstatement;
>          void* sstatement;
>
>      } statement;
> }CStatement;
>
>
> 2)
> typedef struct CStatement
> {
>      int stype;
>
>      void* sstatement;
>
> }CStatement;

Neither appeal too much. How different are all the CXxxxxStatement 
types? Maybe drag in whatever they contain into the Cstatement struct, 
and put in some tag to distinguish them.

For example:

goto        expr
assign      expr expr
ifthen      expr stmt stmt
print       exprlist

Either one, two or three things for each. Each thing is either an 
expression* or statement*, with a list of them perhaps implemented as a 
linked list the head of which is also an expression* or statement*. And 
you might be able to combine expr and stmt as a single expr_or_stmt* type.

-- 
Bartc

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


#65187

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-07-10 21:48 +0100
Message-ID<87io9rwxgh.fsf@bsb.me.uk>
In reply to#65093
janus <emekamicro@gmail.com> writes:

> I have 2 options but which one is idiomatic C?
>
> 1)
> typedef struct CStatement
> {
>     int stype;
>
>     union Statement
>     {
>         CPrintStatement* printstatement;
>         CInputStatement* inputstatement;
>         CAssignStatement* assignstatement;
>         CGotoStatement* gotostatement;
>         CIfThenStatement* ifthenstatement;
>         void* sstatement;
>
>     } statement;
> }CStatement;
>
>
> 2)
> typedef struct CStatement
> {
>     int stype;
>
>     void* sstatement;
>
> }CStatement;

I'd like to offer a third:

  typedef struct CStatement CStatement;

That's all that anyone usually sees, so you have to pass these things
around as pointers -- usually with a const on the target type.

Only in once place (one translation unit as C calls them, but it's C's
idea of a module) do you expand on this.  In that module, I'd use

  struct CStatement
  {
      int stype;
      void *statement;
  };

and provide a number of type-safe interface functions:

  void set_printstatement(CStatement *stmt, const CPrintStatement *cps)
  {
        stmt->stype = PRINT;
        stmt->statement = cps;
  }

  CPrintStatement *get_printstatement(const CStatement *stmt)
  {
        return stmt->stype == PRINT ? stmt->statement : NULL;
        /* Or do some other sort of error handling */
  }

There are a gazillion ways to make the definitions simpler to write and
maintain but I hope you get the drift.  The point is to hide this
implementation detail behind an opaque type.  You may be writing the
rest of the code so it might seem like you could simply impose on
yourself some good behaviour rules about access to this structure but I
find I like to keep myself out of the parts of my code where I don't
belong (most of the time).

-- 
Ben.

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


#65189

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2015-07-10 13:51 -0700
Message-ID<d6025b96-21fa-4b77-a363-4c446eafd1d3@googlegroups.com>
In reply to#65187
On Friday, July 10, 2015 at 4:48:39 PM UTC-4, Ben Bacarisse wrote:
> janus <emekamicro@gmail.com> writes:
> 
> > I have 2 options but which one is idiomatic C?
> >
> > 1)
> > typedef struct CStatement
> > {
> >     int stype;
> >
> >     union Statement
> >     {
> >         CPrintStatement* printstatement;
> >         CInputStatement* inputstatement;
> >         CAssignStatement* assignstatement;
> >         CGotoStatement* gotostatement;
> >         CIfThenStatement* ifthenstatement;
> >         void* sstatement;
> >
> >     } statement;
> > }CStatement;
> >
> >
> > 2)
> > typedef struct CStatement
> > {
> >     int stype;
> >
> >     void* sstatement;
> >
> > }CStatement;
> 
> I'd like to offer a third:
> 
>   typedef struct CStatement CStatement;
> 
> That's all that anyone usually sees, so you have to pass these things
> around as pointers -- usually with a const on the target type.
> 
> Only in once place (one translation unit as C calls them, but it's C's
> idea of a module) do you expand on this.  In that module, I'd use
> 
>   struct CStatement
>   {
>       int stype;
>       void *statement;
>   };
> 
> and provide a number of type-safe interface functions:
> 
>   void set_printstatement(CStatement *stmt, const CPrintStatement *cps)
>   {
>         stmt->stype = PRINT;
>         stmt->statement = cps;
>   }
> 
>   CPrintStatement *get_printstatement(const CStatement *stmt)
>   {
>         return stmt->stype == PRINT ? stmt->statement : NULL;
>         /* Or do some other sort of error handling */
>   }
> 
> There are a gazillion ways to make the definitions simpler to write and
> maintain but I hope you get the drift.  The point is to hide this
> implementation detail behind an opaque type.  You may be writing the
> rest of the code so it might seem like you could simply impose on
> yourself some good behaviour rules about access to this structure but I
> find I like to keep myself out of the parts of my code where I don't
> belong (most of the time).
> 
> -- 
> Ben.

That being the case, the OP should use C++ then and make it a class
with encapsulated accessors.

Best regards,
Rick C. Hodgin

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


#65198

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-07-10 23:45 +0100
Message-ID<877fq7ws1q.fsf@bsb.me.uk>
In reply to#65189
"Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:
<snip example of making a "discriminated union" in C>

> That being the case, the OP should use C++ then and make it a class
> with encapsulated accessors.

The OP should *consider* using C++, but saying that they should use C++
is too strong.

This is one of those places where, from the C programmer's point of
view, you have to keep reinventing the wheel.  This problem was solved
decades ago (see, for example, Algol 68) and solved again and again in
various ways every few years or so since.  But all of these solutions
are just a shade above the level that C is pitched at in terms of
programming abstractions.

-- 
Ben.

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


Page 1 of 2  [1] 2  Next page →

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


csiph-web