Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #65093 > unrolled thread
| Started by | janus <emekamicro@gmail.com> |
|---|---|
| First post | 2015-07-10 00:49 -0700 |
| Last post | 2015-07-10 19:12 -0700 |
| Articles | 20 on this page of 33 — 13 participants |
Back to article view | Back to comp.lang.c
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 →
| From | janus <emekamicro@gmail.com> |
|---|---|
| Date | 2015-07-10 00:49 -0700 |
| Subject | Struct 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]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-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]
| From | janus <emekamicro@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-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]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-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]
| From | "Bill Davy" <Bill@SynectixLtd.com> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2015-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]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-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]
| From | David Kleinecke <dkleinecke@gmail.com> |
|---|---|
| Date | 2015-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]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-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]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-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]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-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]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-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