2

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;
};
Machavity
  • 30,841
  • 27
  • 92
  • 100
riverrock
  • 97
  • 2
  • 8
  • It drops the need to use 'struct' everywhere the type is used. The underscore is to prevent name clashes between the non-typedef'ed name and the typedef'ed one – Toby May 17 '17 at 09:36
  • 1
    I don't think it's a good idea. A) it's a standard violation. All identifiers in file scope and tag namespaces starting with an underscore are reserved, B) it unnecessarily litters your global namespace. Unnecessarily, because you can use the same name for your struct tag and for your typedef (`typedef struct foo foo;`) -- a convention that C++ even built into the language. – Petr Skocik May 17 '17 at 09:39
  • "All identifiers in file scope and tag namespaces starting with an underscore are reserved" - U wot? Not quite. – Bathsheba May 17 '17 at 09:41
  • @Bathsheba http://port70.net/~nsz/c/c11/n1570.html#7.1.3 second bulletpoint – Petr Skocik May 17 '17 at 09:43
  • That epitomises why you should never trust anything on the internet ;-) – Bathsheba May 17 '17 at 09:44
  • Typedeffed names with trailing `_t` are reserved, so just dont use them in user code. – wildplasser May 17 '17 at 10:06

4 Answers4

7

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

Community
  • 1
  • 1
Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
3

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:

  1. Don't ever use a double underscore, as formally the behaviour on doing that is undefined.

  2. Don't start a type with a single underscore followed by a capital letter. Again, such type names are reserved.

  3. 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.)

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • The double underscore convention is abhorrent as well, to be perfectly honest. And many C programmers ignore *that* as well. Different levels of caring for portability, I suppose. – StoryTeller - Unslander Monica May 17 '17 at 09:37
  • @StoryTeller: I think that's naughty as it *could* clash with macros defined at leisure by the implementation of your C standard library. (I disallow it in my code base.) – Bathsheba May 17 '17 at 09:38
  • The likelihood of clashing with the standard library is no greater than clashing with POSIX, if one looks at it honestly. I highly doubt `__mycompany_mymodule_mycomponent_hiddenfeature` will clash with anything in the standard library. – StoryTeller - Unslander Monica May 17 '17 at 09:41
  • That's an interesting perspective. For me you should *never* write code that is undefined by standard C. But, facetiously, idealisms emanating from the likes of POSIX and MISRA can be treated as advisory, or passed over as being the musings of a pedant. – Bathsheba May 17 '17 at 09:47
  • True. But the root cause for these prohibitions is the same. Those standards want to future-proof user code. And while I completely agree with you on the leading double underscore, I find it completely arbitrary to disregard POSIX (if one *is* building or may build for a POSIX system). Adhering to such conventions to begin with can make certain transitions smoother. So, perhaps they are not quite so pedantic. Just my 2 pennies worth opinion. – StoryTeller - Unslander Monica May 17 '17 at 09:49
2

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 .

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.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
1

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.

John Bode
  • 119,563
  • 19
  • 122
  • 198