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?
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 ...
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).
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.
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 .
typedef struct _STRUCTNAME
{
// struct contents
} STRUCTNAME;
This piece of code does two things:
struct _STRUCTNAME
andtypedef
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.
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:
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.
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 typedef
s as merely syntactic sugar, but C needs a bit of sugar here and there, otherwise it can seem pretty bland.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With