tags:

views:

491

answers:

15

Typedef is very useful for portable names, tag names (typedef struct foo Foo;) and keeping complicated (function) declarations readable (typedef int (*cmpfunc)(const void *, const void *);).

But are there situations in C where a typedef is really truly needed? Where you cannot accomplish the same by simple writing out the derived type.

To clarify a bit: I mean for language users, not implementers. The whole of stdint.h is a good example of the second category.

Conclusion

Thanks for all your input. I think I can summarise it as:

  • The C99 library needs typedef to implement the various (u)intN_t types.
  • On C89 you really want to use typedefs yourself to create similar portable types.
  • You might need typedef when using the va_arg macro, but I doubt you will encounter these derivative types in practise.
A: 

No. I think I'm safe in saying that!

Oli Charlesworth
... your reasoning being?
bdonlan
A combination of intuition, and the fact that I can't think of a counterexample. It's quite hard to prove a negative! Not worthy of a downvote, really...
Oli Charlesworth
+2  A: 

it is definitely required, a good example is size_t which is typedef'd on various platforms.

You could use `unsigned int` or `unsigned long` in place of size_t, so it's not a great example. Something like `int32_t` would be a better one which might require a different typedef on different platforms.
JeremyP
It is required in the sense of "being able to write platform-independent code". But on a given platform, you could theoretically just substitute in the `typedef` type everywhere.
Oli Charlesworth
As I see it, `size_t` can very well be a distinct type, different from all other unsigned integer types. `intN_T` are required to be typedefs, but see my added note to the question.
schot
The question is if `typedef` is required - the compiler could certainly implement `size_t` with a `#define` or primitive type instead, so this isn't evidence that `typedef` is required.
bdonlan
@schot: `intN_t` are required to be typedefs, but they need not be typedefs for one of the standard integer types (ie `signed char`, `short`, `int`, ...) as the C standard allows for implementation-defined extended integer types
Christoph
A: 

I know of no cases where typedef is explicitly needed in C.

Zor
+1  A: 

Yes. Integer types that have to be a fixed size. e.g. int32_t (and you want your code to have a fighting chance of being portable).

JeremyP
If you want your code to be portable, don't write code which depends upon variable type length in bytes!
Blank Xavier
@Blank Xavier: there are plenty of cross platform applications where you legitimately need integer types of a known size. Anything dealing with binary files or network protocols, for instance.
JeremyP
+9  A: 

A typedef is, by definition, an alias. As such, you always could replace the alias with the actual type. It wouldn't be an alias otherwise.

That doesn't mean avoiding typedef would be a good idea.

jamesdlin
No, I won't avoid `typedef` :) But apparently the evil macro `va_arg` might require a `typedef`. (See my own answer.)
schot
You can *semantically* replace a typedef-name with the actual type. But you can't always replace it *textually*. So, in the code that critically depends on *textual* substitution (macros like `va_arg`, for example), you have no other choice but to use a typedef-name.
AndreyT
Although this might not be 100% good I chose this over my own answer because mine seems a bit to theoretical in retrospect.
schot
+1  A: 

The keyword typedef is definitely needed in test suites that check a C compiler for ISO-C compliance.

In code that is not explicitly supposed to use typedef (like the test suite above) it is often very helpful but never essential because it only establishes an alias to another type. It does not create a type.

Finally, I would not count things like avoiding a compiler limit on preprocessed source file size through the abbreviation typedefs can offer.

Peter G.
+5  A: 

From wikipedia:

typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to assign alternative names to existing types, most often those whose standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another.1

Based on that definition, no it's never required as you can always just write out the expanded form. However, there may be macro definitions which choose a typedef to use based on platform or something else. So always using the expanded form may not be very portable.

jay.lee
+1 for actually answering the question
Isak Savo
You cannot use the fully expanded form in the offsetof() macro.
Sjoerd
And if the name contains a comma, you need a typoedef to use it in macros.
tstenner
@tstenner: What's an example of a name containing a comma?
Oli Charlesworth
@tstenner: Answer my own question: `void(*)(int,int)`. Then yes, this seems to be the canonical counterexample!
Oli Charlesworth
I'm still trying to decide if `typoedef` is brilliant or an accident.
Ken
A: 

Without typedef, you have to use the keyword struct everytime if you use a struct in declarations. With typedef, you can omit this.

struct Person
{
  char * name;
};

struct Person p; /* need this here*/

typedef struct _Person
{
  char * name;
} Person;

Person p; /* with typedef I can omit struct keyword here */
codymanix
Convenience, not necessity.
DevSolar
-1 for using `_Person` - this results in undefined behavior (identifier begins with underscore followed by a capital letter). Also you're inconsistent about whether you use the underscore or not, so as written the code is broken.
R..
Not even convenient - this is evil. Fully obscuring a type is good; PARTIALLY obscuring a type is VERY VERY BAD.
Blank Xavier
@Blank: You argued this yesterday (http://stackoverflow.com/questions/3821112/good-practice-in-c/3821176#3821176), but I've yet to understand why typedef-ing a struct is different to typedef-ing any other type, and why it's "VERY VERY BAD"!
Oli Charlesworth
http://www.45mercystreet.com/computing/typedefs.html
Blank Xavier
Actaully, I need to update that slightly - if the typedefed entity is a struct, it has a unique type of its own, so you don't even get additional type checking (whereas a series of say ints as arguments, where each was given its own type, would produce additional type checking).
Blank Xavier
+1  A: 

The offsetof() macro requires a structname and a membername, and thus cannot be used with inline struct definitions. Well, maybe on your implementation it can, but it isn't guaranteed by the C standard.

Update: As pointed out in the comments, this is possible:

struct blah { int a; int b; };
x = offsetof(struct blah, a); // legal

But inlining the struct definition is not:

x = offsetof(struct {int a; int b;}, a); // illegal

The former does not contain the keyword typedef, but inlining the struct definition is not possible either. Which version is indicated by "simple writing out the derived type" is unclear.

Sjoerd
You can do `struct blah { int a; int b; }; ... offsetof(struct blah, a);`, surely?
Oli Charlesworth
I interpreted the question as asking whether offsetof( struct { int a; int b; } , a) was possible.
Sjoerd
+8  A: 

Thanks all for your answers. I looked some more myself and found this in C99, J.2 Undefined behaviour:

The behavior is undefined in the following circumstances: [...]

  • The type parameter to the va_arg macro is not such that a pointer to an object of that type can be obtained simply by postfixing a * (7.15.1.1).

So when you want to pass/extract complicated derived types to va_arg such as int (*)[] you need to typedef this type to something for which this is possible (updated/corrected):

typedef int (*intarrptr)[4];
intarrptr x = va_arg(ap, intarrptr);

Since it is difficult to find and actual useful case for this one might conclude that it is not a strong argument for the necessity of typedef.

schot
That code doesn't actually make sense (`error: array initialized from non-constant array expression`)...
Oli Charlesworth
@Oli Charlesworth: Yes, I made a mistake in writing this tricky derived type. See the updated example.
schot
@schot: Still not valid. Do you mean `typedef int (*intarrptr)[4];`?
Oli Charlesworth
@R: I understand its contrived because I'm trying to find an example to justify this restriction on `va_arg` given in the C99 standard. Why else would it be there? @Oli: Yes... stupid copy-paste error as I even used cdecl.org the second time.
schot
I think this is the first actual example of where `typedef` would be necessary in user code (as opposed to internal to the compiler's headers, etc). Nice find :)
bdonlan
Still not convinced, because I haven't seen a working example! Can't you wrap the type in parentheses?
Oli Charlesworth
@Oli: In order to get a pointer-to-`int (*)[4]`, it's not sufficient to tack on a `*` at the end - you have to insert it into the middle, as in `int (**)[4]`. However, the va_args macros can't alter the insides of a passed-in parameter, they can only tack on tokens in the end. That's why this restriction is in place.
bdonlan
@bdonlan: Good point.
Oli Charlesworth
A: 

doesn't 'extremely useful' mean requied?

not even hard for me to think about a project with struct for each struct member,pointer,arguement,and so on.

jokester
A: 

To me, typedef provides abstraction. It keeps my code clean and very easy to understand. You can live without typedef just like you can live without all high level languages and sticking with assembly or machine language.

Taimoor
A: 

Individual programmers are not required to create their own typedefs. There's no universal rule saying I can't write things like

int *(*(*x())[5])();

if I so desire (although my company's coding standards may frown on it).

They're all over the standard library, however (FILE, size_t, etc.), so you really can't avoid using typedef names.

John Bode
A: 

We use typedef to at work keep code platform independent. Like for example, we do something like

typedef unsigned char SHORT;

this makes code more readable and easy to port.

arbithero
Consider using the types from stdint.h (uint8_t, int32_t, int_fast8_t, etc.) instead of your own "platform independent" types. A type called `SHORT` has limited meaning to me, and I'd be surprised not only that it wasn't the same as a `short int`, but it's less than 16 bits and unsigned!
tomlogic
A: 

No.

A typedef does not create a truely new type as say a class in C++, it merely creates a type alias - a single identifier for something else that already exists. In a typedef, you define no new behaviour, semantics, conversions or opeators.

Clifford