473,787 Members | 2,989 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Question about a struct declaration

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
Jun 27 '08 #1
21 2011
heavyz <he********@gma il.comwrote:
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
Jun 27 '08 #2
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.

Jun 27 '08 #3
heavyz <he********@gma il.comwrites:
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_Keit h) <ks***@mib.or g>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #4
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
Jun 27 '08 #5
Andrey Tarasevich said:

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

typedef struct dummy *dummy;
Please don't hide pointers in typedefs.
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.
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;
};

--
Richard Heathfield <http://www.cpax.org.uk >
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #6
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
Jun 27 '08 #7
Andrey Tarasevich said:
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.
Er... I disagree.
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.
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?

--
Richard Heathfield <http://www.cpax.org.uk >
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #8
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
Jun 27 '08 #9
Willem wrote:
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.
I understand that perfectly well. I'm taking about the situations when
library specification does not want to restrict implementations to using
pointer types and at the same time does not want to prevent them from
doing that. 'pthreads' library specification is one example of that.

--
Best regards,
Andrey Tarasevich
Jun 27 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
2110
by: ark | last post by:
Hello group, Could you help me with this: static const int x; ............ something ............. static const int x = 17; It looks perfectly legal to me but MSVC/C++ 6.0 gives, on the first line, "warning C4132: 'x' : const object should be initialized" yet generates correct code.
5
3307
by: PCHOME | last post by:
Hello! I am working on dividing a single C file into several files. Now I encounter a problem about the global variables and can not find a way to solve it. All global variables and codes used to be in that single file, that worked OK. But when I divdie that file into several ones, I have many "invalid use of undefined type" errors. The four files are main.c, main.h, readLP.h, and readLP.c. In readLP.h
6
2692
by: S.Tobias | last post by:
I'm trying to understand how structure type completion works. # A structure or union type of unknown # content (as described in 6.7.2.3) is an incomplete type. It # is completed, for all declarations of that type, by ^^^ # declaring the same structure or union tag with its defining # content later in the same scope. ^^^^^ (6.2.5#23)
10
5828
by: James Brown | last post by:
I have the following enum declared: enum TOKEN { TOK_ID = 1000, TOK_NUMBER, TOK_STRING }; (it goes on and on like that) This is what I would like to do: TOKEN t1 = TOK_ID; // ok TOKEN t2 = 5; // compile error (cannot convert from
15
1858
by: sethukr | last post by:
Hi everybody, While running the following program in GCC, i'm very much screwed. main() { char *ptr1; char arr; int i; char *ptr2;
4
2090
by: Marcin Kasprzak | last post by:
Hello Guys, Silly question - what is the most elegant way of compiling a code similar to this one? <code> typedef struct a { b_t *b; } a_t; typedef struct b {
10
2245
by: Raman | last post by:
Hi All, Is it valid: struct test{ }; I mean, Can we have a struct containing no members? Is this a an
8
1572
by: Chad | last post by:
Given the following..... #include <stdlib.h> #include <stdio.h> struct node { int data; struct node *next; };
4
1497
by: Richard Harter | last post by:
I have a couple of questions about the following code fragment: struct list_info { void * first; void * last; }; struct pipe_data_list { void * data; struct agent_port_list * dest;
0
9655
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10363
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9964
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8993
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6749
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5534
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4067
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3670
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2894
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.