#define and typedef

closed account (S6k9GNh0)
As I've come to realize, I find the two more often than usual lately:

1
2
3
#define BOB BOB_struct

typedef BOB_struct BOB;


This performs the exact same to a point. #define simply replaces the context of BOB with BOB_struct and typedef creates a new type which says BOB is BOB_struct. My question now is what is more efficient. If I had the choice of using a defined macro should I use it? Is there harm in using the typedef? My assumption is that a typedef creates a syntax synonym and the compiler excepts it as the equivalent syntax as what the typedef declared. But I have no clue what it actually does so is there any real loss in using it?
Last edited on
The typedef gives information to the compiler about how to interpret an identifier. It produces no code. The typedef is preferable to the macro because it's typed, and thus, less error prone.
Neither is more efficient, as they'll both produce the same binary.

That said... typedef is more prefereable in my book. Avoid #define unless it's your only option.

#defines are done by the preprocessor which is oblivious to the program's context. This leads to obscure compiler errors when used improperly (the compiler error will say something that is not reflected by the code it's referring to at all -- you need to look up and expand the macro to know wtf it's talking about). They also don't work well with debuggers.

#define can also lead to other unexpected errors. What happens if there's a function or local variable in your program which also happens to be named BOB? #define doesn't care, it'll replace it anyway. It also doesn't care about namespace or scope -- a #define anywhere in the program can pollute any and all namespaces/functions/classes. This is a common problem with <windows.h> which #defines its own min/max macros -- which effectively screws you if you try to use std::numeric_limits<type>::max() or the like. You have to explicitly #undef them to avoid those errors.

typedefs are type aware and flow with C++ more naturally, rather than #defines which sort of force their way in.

edit: blargg @ helios quick response ;P at least we're in agreement.
Last edited on
closed account (S6k9GNh0)
Thanks for the reply. I've been told that #define is most useful in functions since you can define a type with a function (I'm not discussing constants). Anyways, I appreciate the feedback and clearing yet another cloud.

I do have another question though. You can define a struct like so:
1
2
3
4
5
typedef struct
{
   int x;
   int y;
} bob;


What is the actual advantage of this method? Doesn't do the same as declaring a struct with a default name? I see this a LOT in almost every C based library I can find.
Last edited on
In C, it didn't create an automatic typedef so you couldn't simply say, create a struct bob and then create instances of it using just bob, you had to use struct bob. The typedef struct way makes it so you can.
A quick Googling of "typedef struct vs struct" reveals that, in C, using that syntax lets you refer to struct bob as just bob.
[off-topic]
I knew a guy named Bob who hated his name for the very reasons illustrated in this thread...
closed account (S6k9GNh0)
LOL! Ask if he's simple like his name. :D
I agree that typedef is preferable to #define only in that C++ programmers tend to strongly dislike macros, which is one of the main purposes of using #define. Although in the case, I hardly call the usage of #define as creating a macro; it is simply creating a more readable name for a type.

Unfortunately for the purposes of creating a new name for an existing type, both #define and typedef suck. The reason is because neither creates a strong type. For example:

1
2
3
4
5
6
7
8
9
10
typedef int Fruit;
typedef int Vegetable;

static const int Apple = 1;
static const int Banana = 2;

static const int Corn = 1;
static const int Peas = 2;

Vegetable favorite_veg = Apple;  // (!) Works just fine! 

But isn't that what enums are for?

1
2
3
4
enum Fruit { Apple, Banana };
enum Vegetable { Corn, Peas };

Vegetable favorite_veg = Apple;  // error 


I actually kind of prefer that typedef doesn't make a strong type. At least in some situations. I agree, though, that it might not be preferable sometimes. Perhaps there should be a modifier for it, like explicit typedef etc to make it a strong type.

But whatever, it is what it is.
But what if you want to assign a uint32_t to a ulong? The two types are compatible, so why should the compiler complain if the typedefs are different?
Topic archived. No new replies allowed.