2

I have come across the following problem, and I could not find any specific explanations as to: Why does C bother to provide type definitions ? Isn't defining BOOL macro just as good as defining Bool type using typedef?

For example, #define directive can be used to create a macro that could be used as a Boolean type:

#define Bool int

There's another way to set up a Boolean type, using a feature known as type definition.

typedef int Bool;

Why is the last method preferred? What are the advantages?

  • 1
    There is no `BOOL` macro in C, nor a built-in `bool` type. There is, however a boolena type `_Bool` which should be used instead of homebrew `typedef`s or macros. Re your question: this is **not** preferred and strongly discouraged. – too honest for this site Feb 21 '17 at 13:48
  • 1
    Note that C's `_Bool` is a type different from the result of OP's `typedef int Bool ;` in many functionally attributes. `Bool` here is not a good example to demonstrate OP's `typedef` vs. `#define` concerns. – chux - Reinstate Monica Feb 21 '17 at 13:48
  • @chux: Siple example where they differ: `_Bool b = 5; printf(%d", b);`. Try this with a `typedef`ed `int`. – too honest for this site Feb 21 '17 at 13:50
  • 1
    _Bool is potentially a bad example because it's a builtin with semantics that aren't achievable with a typedef. – Petr Skocik Feb 21 '17 at 13:52
  • @Olaf, my concern was/is why isn't defining a BOOL macro just as good as defining a Bool type using typedef, just as the question states. I do not understand why it is unclear as I have stated my concerns in the question. As pointed out, however, it seems that I have used a bad example by using Bool. –  Feb 21 '17 at 13:56
  • @Rizzo: For a boolean type, both are wrong, because you just can't. For the others, your question seems to boil down to "what's the difference between macros and declarations?". It is not really related to `typedef` nor other constructs actually. – too honest for this site Feb 21 '17 at 13:58
  • 1
    @Rizzo C has a real _Bool. It's different from any other integer type in that that any nonzero value stored into it is stored as one and zeros stored into it are stored as zeros. You can't get that with a typedef (overflows and narrowing truncations get in the way). That's what probably ticks nitpickers off about your question (which is, otherwise, a very good question, IMO). – Petr Skocik Feb 21 '17 at 14:23

2 Answers2

10

There are two important differences between type definitions and macro definitions.

Type definitions are more powerful than macro definitions. In particular, array and pointer types can't be defined as macros. Suppose that we try to use a macro to define a "pointer to integer" type:

  #define PTR_TO_INT int *

The declaration

  PTR_TO_INT p, q, r

will become

  int * p, q, r

after preprocessing. Unfortunately, only p is a pointer; q and r are ordinary integer variables. Type definitions don't have this problem.

Second, typedef names are subject to the same scope rules as variables; a typedef name defined inside a function body wouldn't be recognized outside the function. Macro names, on the other hand, are replaced by the preprocessor wherever they appear.

  • 1
    Object-pointers should never be `typedef`ed anyway. And arrays only if well thought. – too honest for this site Feb 21 '17 at 13:55
  • 1
    A weakness here is that a problems of `#define PTR_TO_INT int *` is discussed, yet a solution using `typedef` is not shown` - IOWs, a one sided argument. `typdef int * ptr_to_int;` is not a winning solution ether. – chux - Reinstate Monica Feb 21 '17 at 13:56
  • 1
    @chux "`typdef int * ptr_to_int;` is not a winning solution ether." It certainly wins over `#define PTR_TO_INT int *`. In such a situation, I fail to see what's wrong with `typedef`. `typedef` certainly makes complex definitions and declarations such as function pointers in structures that take functions as arguments a lot easier to understand. – Andrew Henle Feb 21 '17 at 15:17
  • @AndrewHenle `#define PTR_TO_INT int *` is a [paper tiger](https://en.wikipedia.org/wiki/Paper_tiger) Of course some `typdef` is better than `#define PTR_TO_INT int *`, yet this answer still lacks a specific example of how to use `typedef` in that case and how that is good. – chux - Reinstate Monica Feb 21 '17 at 15:36
  • @chux, why would something like this not be considered good practice, or a "winning solution" ? `typedef int* IntPtr ; IntPtr x, y, z;` –  Feb 25 '17 at 20:58
  • The semantics of C are too readily confused when an object is mistaken between an object and an object pointer. `IntPtr x` gains little over `int *x;`. http://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers cover more details. – chux - Reinstate Monica Feb 26 '17 at 03:14
8

Apart from the above mentioned reasons, one more thing, a MACRO can be undefined and redefined, but not a typedef. So, from one perspective, a typedef is more definitive.

For example

#define MAX 5

//some use of MAX

#undef MAX
#define MAX 10

// some more use of MAX

is perfectly valid, but an attempt to do something like

typedef int into;

///something....

typedef char into;

is invalid, as the "type" is already defined previously.

So, typedef, which creates an alias to a "type", is considered much more consistent, in that regard.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261