Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Question about a struct declaration

Reply
Thread Tools

Question about a struct declaration

 
 
heavyz
Guest
Posts: n/a
 
      04-16-2008
In C, if i want to declare a struct, there are 3 methods to do so:

1: struct dummy { ... };
2: typedef struct { ... } dummy;
3: typedef struct _dummy { ... } dummy;

Usually i use the first method to declare my structs, but in many open
source projects (such as libxml2), the third method is used. I am just
curious about the difference.. Would somebody tell me which method is
recommended, and why? Thanks in advance.

ZHENG Zhong
 
Reply With Quote
 
 
 
 
Richard Bos
Guest
Posts: n/a
 
      04-16-2008
heavyz <(E-Mail Removed)> wrote:

> In C, if i want to declare a struct, there are 3 methods to do so:
>
> 1: struct dummy { ... };
> 2: typedef struct { ... } dummy;
> 3: typedef struct _dummy { ... } dummy;

^^^^^^
This is unwise. Identifiers beginning with _ and a lower-case letter are
only allowed for the compiler itself, not for you, except when they're
declared at block scope; but most struct types (a.o.t. struct _objects_)
are not declared at block scope, because they're more useful with file
scope. (And identifiers beginning with _ and an upper-case letter or
with __ are not allowed for us mere users, full stop.)
The different identifiers are unnecesary, anyway. C has separate
namespaces for struct identifiers and for normal ones, so "struct dummy"
and plain "dummy" do not clash, which means that

typedef struct dummy { ... } dummy;

is (when fleshed out, of course) a perfectly valid declaration of both a
struct type and a typedef'ed alias for it; and IYAM, if you want or need
to use both a struct name and a typedef for it, having them both the
same is clearer, as well.

> Usually i use the first method to declare my structs, but in many open
> source projects (such as libxml2), the third method is used. I am just
> curious about the difference.. Would somebody tell me which method is
> recommended, and why? Thanks in advance.


In most aspects it's a matter of taste, but IMO, unless you have good
reason not to, the first one is best, because it's simplest.
One good reason not to would be if you're creating an abstract data type
library and do not want to tell your users how you're implementing your
ADT; you'd then keep your struct definition in the ADT library code
itself, and only put the typedef in the associated header.

Richard
 
Reply With Quote
 
 
 
 
Martin Ambuhl
Guest
Posts: n/a
 
      04-16-2008
heavyz wrote:
> In C, if i want to declare a struct, there are 3 methods to do so:
>
> 1: struct dummy { ... };
> 2: typedef struct { ... } dummy;
> 3: typedef struct _dummy { ... } dummy;
>
> Usually i use the first method to declare my structs, but in many open
> source projects (such as libxml2), the third method is used. I am just
> curious about the difference.. Would somebody tell me which method is
> recommended, and why? Thanks in advance.


#1 is a structure-type-definition. It is sufficient and rarely is more
needed. The
type thoughout the code is 'struct dummy' unless there is a later
typedef.

#2 and #3 are used to provide an alias for the struct.
In #2, there is no alias tag and so the type must be 'dummy' throughout.
This hides the fact that it is a struct and is probably a bad idea.
In #3, you create two names for the type, 'struct _dummy' and 'dummy'.
It is bad idea to use identifiers that begin with underscores unless you
are thoroughly familiar with the exact restrictions on such names. That
you are asking this question suggests that you are not. So #3 could be
done as either (note the absence of the underscore)
3a. typedef struct dummy { /* ... */ } dummy;
or in two parts;
3b. struct dummy { /* ... */ }; /* structure-type-definition */
typedef struct dummy dummy; /* typedef creating alias */

I prefer #1 in almost all situations.

#2 is probably better than your #3 or my #3a or #3b, since there is a
point to not having two ways of identifying the type. Of #3, #3a, and
#3b, #3 is the worst. #3b has real uses: namely to provide a
structure-type-definition in implementation files and providing a
typedef in a header where you want to make the type opaque to the user,
and he will refer to objects only through pointers to them.

Decide how you want the programmer to refer to a struct. If you want
him to use 'struct dummy', use #1. If you want him to use 'dummy', use
#2. If you want opaque datatypes referred to though pointers of the
type 'dummy *', use #3b.

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      04-16-2008
heavyz <(E-Mail Removed)> writes:
> In C, if i want to declare a struct, there are 3 methods to do so:
>
> 1: struct dummy { ... };
> 2: typedef struct { ... } dummy;
> 3: typedef struct _dummy { ... } dummy;
>
> Usually i use the first method to declare my structs, but in many open
> source projects (such as libxml2), the third method is used. I am just
> curious about the difference..


Method 2 has the disadvantage that there's no name for the type until
you reach the end of the declaration, so you can't declare a member of
type "dummy*" (e.g., for a node in a tree or linked list).

Method 3, as Richard Bos pointed out, infringes on the
implementation's name space. This can be fixed by using the same
identifier for the typedef and the struct tag:

typedef struct dummy { ... } dummy;

or by using some other convention if you don't like re-using the same
identifier for some reason (perhaps due to a limitation in your
development environment):

typedef struct dummy_s { ... } dummy;

> Would somebody tell me which method is
> recommended, and why? Thanks in advance.


All three are recommended. It just depends on who you ask. This
happens to be a controversial issue (but not one that most of us get
too worked up about).

Personally, I prefer method 1 unless there's a good reason to hide the
fact that the type is a struct. Others will prefer method 2 or 3
because they like to have a single-word name for the type and don't
feel the need to be reminded that it's a struct every time they
mention it.

If you're working on existing code, follow the style used in that
code; consistency is more important than any small benefit one style
might have over another. If you're writing your own original code,
pick a style and stick to it; you're free to follow either my advice,
or the advice of those poor misguided souls who disagree with me for
their own unfathomable reasons.

--
Keith Thompson (The_Other_Keith) <(E-Mail Removed)>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Andrey Tarasevich
Guest
Posts: n/a
 
      04-16-2008
heavyz wrote:
> In C, if i want to declare a struct, there are 3 methods to do so:
>
> 1: struct dummy { ... };
> 2: typedef struct { ... } dummy;
> 3: typedef struct _dummy { ... } dummy;
>
> Usually i use the first method to declare my structs, but in many open
> source projects (such as libxml2), the third method is used. I am just
> curious about the difference.. Would somebody tell me which method is
> recommended, and why? Thanks in advance.


In the method 1 you'll have to refer to your data type as 'struct dummy'
all the time, i.e. use two words. I personally don't consider this a big
problem, but many people might prefer to be able to refer to such type
with one word instead of two. So, they create a typedef name for the
type, as in the method 3. Now they can refer to it as 'dummy'.

The same effect can be achieved by an additional typedef in after the
method 1 declaration:

typedef struct dummy dummy;

Note that it is not really necessary to use a different identifier for
the struct tag and for the typedef name (and using a name that begins
with a '_' is not a good idea in any case). This is perfectly valid as well

typedef struct dummy { ... } dummy;

However, if one day you'll need to do something like that

typedef struct dummy *dummy;

and use it as a dual-language header (C and C++) you'll run into
problems with C++, wince in C++ the latter declaration is illegal. If
this is an issue in your case, then it is a good idea to choose
different identifiers for struct tag and the typedef name. Otherwise,
the same identifier can safely be used (unless I'm missing some other
issue).

The method 2 might be OK, but, as others already mentioned, it won't
work in case when you need to self-refer to the struct type from inside
if its definition.

--
Best regards,
Andrey Tarasevich
 
Reply With Quote
 
Andrey Tarasevich
Guest
Posts: n/a
 
      04-16-2008
Richard Heathfield wrote:
> Andrey Tarasevich said:
>> However, if one day you'll need to do something like that
>>
>> typedef struct dummy *dummy;

>
> Please don't hide pointers in typedefs.


Er... There are situations when you don't, and there are situations when
that the correct thing to do.

If want to use the type as a pointer (i.e. keep its pointer nature
exposed to the client), then hiding the fact that it is a pointer in a
typedef is indeed a pretty useless idea.

However, if you want to declare a generic "handle" type, whose specific
nature is not supposed to be exploited by the user in any way, a pointer
hidden in a typedef is a standard, widely used and accepted idiom. A
classic example would be the interface of 'pthreads' library, where
'pthread_t', 'pthread_mutex_t' etc. might easily be pointers (or might
not be pointers). If they are in fact pointers in a given
implementation, you'll probably see typedefs in the interface header
file that'll look pretty much as the one above. And there's nothing
wrong with it.

>> The method 2 might be OK, but, as others already mentioned, it won't
>> work in case when you need to self-refer to the struct type from inside
>> if its definition.

>
> I'm surprised that nobody has yet mentioned the very simple solution to
> this problem: i.e. forward declaration.
>
> typedef struct dummy_ dummy;
>
> struct dummy_
> {
> dummy *prev;
> dummy *next;
> int data;
> };



I don't exactly see how it applies to method 2 (since that's what I was
talking about), since method 2 is specifically about the _anonymous_ struct.

As for the other methods, nobody mentioned that "simple solution to this
problem" simply because nobody thinks there's a problem here. Your
solution is in no way simpler that using struct tag to self-refer to a
tagged struct type. All these methods are in the FAQ anyway.

--
Best regards,
Andrey Tarasevich
 
Reply With Quote
 
Andrey Tarasevich
Guest
Posts: n/a
 
      04-16-2008
Richard Heathfield wrote:
> ...
> Er... I disagree.


Well, then, can you come up with a different implementation hiding
technique that would satisfy the following two requirements:

1) Client code can define objects of type 'T'
2) Client code doesn't see the implementation details of the concept
type 'T' represents
?

I actually can do that, but one alternative technique I know is no
better then a typedef-ed pointer.

>> If want to use the type as a pointer (i.e. keep its pointer nature
>> exposed to the client), then hiding the fact that it is a pointer in a
>> typedef is indeed a pretty useless idea.
>>
>> However, if you want to declare a generic "handle" type, whose specific
>> nature is not supposed to be exploited by the user in any way,

>
> ...it's *still* a bad idea to hide pointeriness from the user - in my
> opinion, of course. This is, however, not a matter of C correctness.


Hide the pointeriness? No, it actually _doesn't_ hide the pointeriness.
The pointeriness will be clearly visible in the interface header, in the
typedef. The important part of the concept of a "handle" is that the
inner workings of the attached entity are hidden, but the facts that the
handle itself is small, copyable with '=' (and copyable efficiently),
comparable with '==', etc. remain exposed. This is what is conveyed
through pointeriness in this case.

>> a pointer
>> hidden in a typedef is a standard, widely used and accepted idiom.

> Yeah, well, I've only got one pair of 'ands, ain't I?


I don't know what to say...

--
Best regards,
Andrey Tarasevich
 
Reply With Quote
 
Willem
Guest
Posts: n/a
 
      04-16-2008
Andrey wrote:
) Richard Heathfield wrote:
)> ...
)> Er... I disagree.
)
) Well, then, can you come up with a different implementation hiding
) technique that would satisfy the following two requirements:

Richard doesn't want you not to use typedef'd pointers like that,
he wants you to typedef the pointer as typedef T <something>
and then have the client code use it as *T

In other words: hide the type, but don't hide the pointeryness.


At least I think that's what he means.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
Reply With Quote
 
Richard
Guest
Posts: n/a
 
      04-16-2008
Andrey Tarasevich <(E-Mail Removed)> writes:

> Richard Heathfield wrote:
>> ...
>> Er... I disagree.

>
> Well, then, can you come up with a different implementation hiding
> technique that would satisfy the following two requirements:
>
> 1) Client code can define objects of type 'T'
> 2) Client code doesn't see the implementation details of the concept
> type 'T' represents
> ?
>
> I actually can do that, but one alternative technique I know is no
> better then a typedef-ed pointer.
>
>>> If want to use the type as a pointer (i.e. keep its pointer nature
>>> exposed to the client), then hiding the fact that it is a pointer in a
>>> typedef is indeed a pretty useless idea.
>>>
>>> However, if you want to declare a generic "handle" type, whose specific
>>> nature is not supposed to be exploited by the user in any way,

>>
>> ...it's *still* a bad idea to hide pointeriness from the user - in
>> my opinion, of course. This is, however, not a matter of C
>> correctness.

>
> Hide the pointeriness? No, it actually _doesn't_ hide the
> pointeriness. The pointeriness will be clearly visible in the
> interface header, in the typedef.


Exactly. Its not clearly indicated at the line its used. Its one of the
few times I would agree with Heathfield on a style issue. In the same
vein I despise C++ for allowing operator overloading - its nigh on
impossible to "read" the code unless you have the brain the size of a
planet and have memorized all the class subtleties. its also why I
always "read" code in a debugger by stepping through. Those nice little
"variable changed" indicators are a great help.

 
Reply With Quote
 
Willem
Guest
Posts: n/a
 
      04-16-2008
Richard Heathfield wrote:
) Um, not quite. I *don't* want to typedef the pointer in any way at all.
) Rather, I want to expose the pointeriness (or, if you prefer,
) pointeryness), by leaving the * out of the typedef altogether, and letting
) the user-programmer stick it in instead.

Er, yes, that was poorly worded of me. I meant to say what you just said.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can *common* struct-members of 2 different struct-types, that are thesame for the first common members, be accessed via pointer cast to either struct-type? John Reye C Programming 28 05-08-2012 12:24 AM
struct declaration into another struct slocum C++ 3 04-11-2008 09:42 AM
struct declaration (silly question) Marcin Kasprzak C Programming 5 03-03-2008 09:50 AM
Initialize pointer-to-struct declaration to an unnamed struct? Ehud Shapira C++ 20 06-30-2007 04:10 PM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM



Advertisments