Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ How to protect oneself from stdio.h macros

Tags:

c++

macros

I spent a long time trying to figure out why the following wouldn't compile:

enum IPC_RC {OK, EOF, ERROR, NEW };

The error message said only something to the effect that it wasn't expecting to see an open parenthesis. It wasn't until I tried compiling it on a more modern compiler that I learned:

/usr/include/stdio.h:201:13: note: expanded from macro 'EOF'
#define EOF     (-1)

So I've finally been burned by a macro! :)

My code doesn't #include <stdio.h> (I don't include anything with a .h suffix), but clearly something I included resulted in the inclusion of <stdio.h>. Is there any way (namespaces?) to protect myself, without tracing down exactly where it was included?

like image 790
Chap Avatar asked Jul 23 '13 02:07

Chap


2 Answers

Namespaces will not be a solution because macros ignore them.

So you have two options:

  • get rid of those macros yourself:

    #ifdef EOF
    #undef EOF
    #endif
    
  • use a prefix with your enum values:

    enum IPC_RC
    {
        IPC_OK,
        IPC_EOF,
        IPC_ERROR,
        IPC_NEW
    };
    
like image 132
Zaffy Avatar answered Nov 14 '22 23:11

Zaffy


I don't know a satisfactory solution to the problem you describe, but I just wanted to share one way to handle the situation. Every now and then you (have to) use some particularly obnoxious header which redefins a good part of the English language. The X11 headers of Python.h come to mind. What I ended up doing - and it worked out very well - is that (usually after I notice the breakage) I wrap the 3rd party header in my own header and deal with the uglyness there.

For instance, in projects which make use of the Ruby interpreter, I usually don't include ruby.h directory but rather include an ourruby.h file which looks something like this:

#ifndef RUBY_OURRUBY_H
#define RUBY_OURRUBY_H

// In Ruby 1.9.1, win32.h includes window.h and then redefines some macros
// which causes warnings. We don't care about those (we cannot fix them).
#ifdef _MSC_VER
#  pragma warning(push)
#  pragma warning(disable:4005)
#endif
#include <ruby.h>
#ifdef _MSC_VER
#  pragma warning(pop)
#endif

// In Ruby 1.8.7.330, win32.h defines various macros which break other code
#ifdef read
#  undef read
#endif
#ifdef close
#  undef close
#endif
#ifdef unlink
#  undef unlink
#endif
// ...

#endif // !defined(RUBY_OURRUBY_H)

That way, I don't have to take care of remembering the fact that some headers are not exactly namespace clean.

like image 40
Frerich Raabe Avatar answered Nov 15 '22 01:11

Frerich Raabe