Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C style struct declaration

Tags:

c

struct

I have a quick question about C style struct's. I was digging through some sample code and found a struct declared in the following way:

typedef struct _STRUCTNAME
{
   // struct contents
} STRUCTNAME;

Please note the lack of an underscore on the second time STRUCTNAME shows up. My understanding was that this would declare a single _STRUCTNAME called STRUCTNAME and no more objects of this struct could be instantiated.

However, this does not seem to be the case. A struct of this type was never actually instantiated in the code except in one place: in a global array of such objects that was used in random places:

const struct STRUCTNAME ARRAYNAME[] = 
{
   // various STRUCTNAMEs declared here
};

Note the lack of an underscore again (which I thought was the name of the instantiated object?)

Is my understanding completely off?

Could someone explain?

like image 946
Klauss Avatar asked Jul 25 '11 05:07

Klauss


People also ask

What is struct declaration in C?

A struct in the C programming language (and many derivatives) is a composite data type (or record) declaration that defines a physically grouped list of variables under one name in a block of memory, allowing the different variables to be accessed via a single pointer or by the struct declared name which returns the ...

Can you forward declare a struct?

In C++, classes and structs can be forward-declared like this: class MyClass; struct MyStruct; In C++, classes can be forward-declared if you only need to use the pointer-to-that-class type (since all object pointers are the same size, and this is what the compiler cares about).

How does typedef struct work in C?

The C language contains the typedef keyword to allow users to provide alternative names for the primitive (e.g.,​ int) and user-defined​ (e.g struct) data types. Remember, this keyword adds a new name for some existing data type but does not create a new type.

Do structs go in header files?

If the struct is to be used by other compilation units (. c files) , place it in the header file so you can include that header file wherever it is needed. If the struct is only used in one compilation unit (. c file), you place it in that .


3 Answers

typedef struct _STRUCTNAME
{
   // struct contents
} STRUCTNAME;

This piece of code does two things:

  1. Defines a structure called struct _STRUCTNAME and
  2. Creates a typedef of that structure called STRUCTNAME.

The reason for this is that in proper C code, the way you would otherwise declare a struct (like the above) would be the following:

struct _STRUCTNAME structInstance;

However, with the typedef in place, you can simply use the following:

STRUCTNAME structInstance;

The same holds true for enum declarations.

like image 81
Adam Maras Avatar answered Oct 27 '22 00:10

Adam Maras


STRUCTNAME is the typedef name.

_STRUCTNAME is the 'tag' for the struct, which is in a different namespace.

Prior to the ANSI standardization, the structure tag namespace wasn't separate in many compilers, so to prevent a name collision with the typedef name it had to be different. However, since standardization there is no need for the tag name to be different.

You see this idiom often used in Windows code, no doubt because it was that way in many examples from the SDK. Raymond Chen wrote a blog post about it a while back:

  • Why are structure names different from their typedef names?

Also, I'm sure there will be some comments about how the _STRUCTNAME identifier is reserved for the implementation, so it's not a good idea to use that form in any case.

like image 35
Michael Burr Avatar answered Oct 27 '22 00:10

Michael Burr


Michael Burr said:

Also, I'm sure there will be some comments about how the _STRUCTNAME identifier is reserved for the implementation, so it's not a good idea to use that form in any case.

OK, I'm game (but I wanted some formatting so you get an answer instead):

A language standard is a contract between compiler-writer and compiler-user, where each promises to do and not do certain things.

Most identifiers beginning with _ are reserved for the implementation - including all identifiers beginning with _ followed by an uppercase letter. This means that the compiler-writer is allowed to use them for any purpose whatsoever, because the compiler-user has promised not to use them.

Compiler-users who break their promise get weird results.

Conversely, all identifiers that the [applicable] standard does not reserve for the implementation are guaranteed to be available to the compiler-user because the compiler-writer has promised not to use them.

Compiler-writers who break their promise get refund demands, when valid code gets weird results.

My preference is to put a trailing _ on tag names, include guards, etc., ensuring that I stay out of the implementation's space; thus:

typedef struct STRUCTNAME_
{
   // struct contents
} STRUCTNAME;

(Some purists frown on typedefs as merely syntactic sugar, but C needs a bit of sugar here and there, otherwise it can seem pretty bland.)

like image 41
mlp Avatar answered Oct 27 '22 00:10

mlp