Reputation: 107
In the source code below, could somebody explain the rational (why is it good programming practice to typedef
the struct _lwm2m_object_t
with the new name lwm2m_object_t
? All it does is drop the underscore? Why is an underscore used in the first instance?
typedef struct _lwm2m_object_t lwm2m_object_t;
typedef uint8_t (*lwm2m_read_callback_t) (lwm2m_uri_t * uriP, char ** bufferP, int * lengthP, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_write_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_execute_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_create_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP);
typedef uint8_t (*lwm2m_delete_callback_t) (uint16_t id, lwm2m_object_t * objectP);
typedef void (*lwm2m_close_callback_t) (lwm2m_object_t * objectP);
struct _lwm2m_object_t
{
uint16_t objID;
lwm2m_list_t * instanceList;
lwm2m_read_callback_t readFunc;
lwm2m_write_callback_t writeFunc;
lwm2m_execute_callback_t executeFunc;
lwm2m_create_callback_t createFunc;
lwm2m_delete_callback_t deleteFunc;
lwm2m_close_callback_t closeFunc;
void * userData;
};
Upvotes: 3
Views: 6759
Reputation: 73444
[Edit 2024] Note though that GCC Reserved Names says:
Names that end with ‘_t’ are reserved for additional type names.
Identifiers ending with _t are also reserved under POSIX: ANY header _t
A leading underscore is used for different purposes by every person or team. Read more in this answer, specifically the paragraph that is dedicated to c.
I usually see this:
typedef struct lwm2m_object lwm2m_object_t;
where one will append a _t
to the struct's name, denoting to the reader that this is a typedef'ef name.
Upvotes: 3
Reputation: 123598
By itself, the leading underscore has no intrinsic meaning, it just creates a distinct identifier for the tag name vs. the typedef name. You could achieve the same result with
typedef struct foo fooType;
Tag names occupy a different namespace from ordinary identifiers, so you can write
typedef struct foo foo;
which some people consider confusing. I don't - the tag name is disambiguated by the presence of the struct
(or union
or enum
) keyword.
You should not use leading underscores in your identifiers - identifiers with two leading underscores or a leading underscore followed by a capital letter are always reserved for the implementation for any use, while identifiers with a single leading underscore are reserved in the ordinary and tag name spaces.
You could use a trailing underscore for the same effect
typedef struct foo_ foo;
and satisfy everybody.
Upvotes: 1
Reputation: 8614
Actually if you use
typedef struct lwm2m_object_t lwm2m_object_t;
struct lwm2m_object_t {
//
}
It will still be allowed by C. This is because the structure names and the typedef identifiers have different namespaces. Please see Why doesn't ANSI C have namespaces? for information about namespaces in C.
However, many professional users avoid this and use different names for structures and typedefs. MISRA1 also disallows this.
Rule 5.6 (advisory): No identifier in one name space should have the same spelling as an identifier in another name space, with the exception of structure member and union member names. [MISRA C 2004]
The use of underscore is just a convention that some people follow. You can follow other conventions, e.g.
typedef struct sTag_lwm2m_object_t lwm2m_object_t;
struct sTag_lwm2m_object_t {
//
}
1 https://en.wikipedia.org/wiki/MISRA_C
Upvotes: 7
Reputation: 234875
Writing typedef struct _lwm2m_object_t lwm2m_object_t;
means that you don't need to write the more verbose struct _lwm2m_object_t
when you want to refer to the struct
type, but you can use lwm2m_object_t
directly instead. It saves typing and can make source code clearer.
Prefixing the actual struct
name with a single _
is a convention that's grown up over the years. And many folk use _t
as a suffix to denote a type.
But a few things to note:
Don't ever use a double underscore, as formally the behaviour on doing that is undefined.
Don't start a type with a single underscore followed by a capital letter. Again, such type names are reserved.
POSIX explicitly forbids your ending your own type with _t
, but note that standard C allows it.
Many experienced C programmers find (3) abhorrent and ignore it. (I do.)
Upvotes: 4