Is There a Clean Way to Prevent Windows.H from Creating a Near & Far MACro

Is there a clean way to prevent windows.h from creating a near & far macro?

You can safely undefine them, contrary to claims from others. The reason is that they're just macros's. They only affect the preprocessor between their definition and their undefinition. In your case, that will be from early in windows.h to the last line of windows.h. If you need extra windows headers, you'd include them after windows.h and before the #undef. In your code, the preprocessor will simply leave the symbols unchanged, as intended.

The comment about older code is irrelevant. That code will be in a separate library, compiled independently. Only at link time will these be connected, when macros are long gone.

#define far, #define near Windef.h

Don't reuse them. The last thing you need is to have to repeatedly explain to people that they aren't the old-school ornaments.

If it is critical to your app, you might consider using capitalized versions (since identifiers are case sensitive) - the compiler will catch typos when you mess up.

Just accept that this is cruft from the good old days when computers were still made from metal.

peculiar bug - parameter doesn't exist yet builds, until name of parameter changes then it breaks more favourably

Judging by the error format you are using MSVC and likely affected by unhygienic includes of Windows headers somewhere in your project (windef.h or windows.h being the likely culprits).

These headers have a tendency to define a lot of macros that frequently conflict with the user code in subtle ways. In your particular case you seem to be affected by far and near macros, which usually expand to nothing.

As suggested in this related SO question you can simply #undef them in the appropriate place. Although I would also consider your #include hierarchy to limit windows-specific headers' scope.

near and far get defined in gl3w?

near and far were used to indicate types of pointers, and are likely to be defined as

#define near
#define far

Which leaves you with

void f(int , int )
{

}

Which is an invalid function definition in C. (arguments must have a name). either undefine them (#undef) or change the argument names. Note that this is not a problem in function declaration (i.e. void foo(int, int); - as in header files) only in function definitions.

Specifically, gl3w.h contains gl3.h which contains windows.h

Workaround to get codes to work in MSVC++ 2010 due to Type name is not allowed

The reason is that near and far are already #defined elsewhere as something else. This is typical if you have already included windows.h, which includes windef.h with following macros:

#define far
#define near
#if (!defined(_MAC)) && ((_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED))
#define pascal __stdcall
#else
#define pascal
#endif

Try changing names into something like plane_near and plane_far and it will work.

VS 2008 C++ error C2059 and C2238

Chances are you're including a windows header before that one, and near and far are defined somehwere in there. Those are (legacy) things from the 16bit era.

See this related question Is there a clean way to prevent windows.h from creating a near & far macro? for workarounds.

Why not include all the standard headers always?

Besides

  • namespace pollution
  • compilation time (although reducable by precompiled headers, it will hurt those compiling a large project once because they actually want to use it, and not develop - also you want to think about rebuilds which are necessary once in a while)

you named "Less figuring out which headers I need and in which header a certain function is" as a benefit. I agree so far as this can be true for well designed libraries and headers.

In practice however I experienced (at least with MFC/ATL) some errors which could be solved by figuring out the correct order of includes. On the other hand one day you want to resolve an issue which makes you travel across the included headers - now imagine yourself looking at tons of headerfiles actually having nothing to do with your code file.

My conclusion is: The time you save by including a bunch of unnecessary headers do not pay off if you have to maintain a large project later on. The more time you invest before starting including any headers, the more time you will safe afterwards - but mostly without actually recognizing it.

Construct path for #include directive with macro

I tend to agree with the comment in utnapistim's answer that you shouldn't do this even though you can. But, in fact, you can, with standard-conformant C compilers. [Note 1]

There are two issues to overcome. The first one is that you cannot use the ## operator to create something which is not a valid preprocessor token, and pathnames do not qualify as valid preprocessor tokens because they include / and . characters. (The . would be ok if the token started with a digit, but the / will never work.)

You don't actually need to concatenate tokens in order to stringify them with the # operator, since that operator will stringify an entire macro argument, and the argument may consist of multiple tokens. However, stringify respects whitespace [Note 2], so STRINGIFY(Dir File) won't work; it will result in "directory/ filename.h" and the extraneous space in the filename will cause the #include to fail. So you need to concate Dir and File without any whitespace.

The following solves the second problem by using a function-like macro which just returns its argument:

#define IDENT(x) x
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define PATH(x,y) STR(IDENT(x)IDENT(y))

#define Dir sys/
#define File socket.h

#include PATH(Dir,File)

Warning: (Thanks to @jed for passing on this issue.) If the strings being concatenated contain identifiers which are defined elsewhere as macros, then unexpected macro substitution will occur here. Caution should be taken to avoid this scenario, particularly if Dir and/or File are not controlled (for example, by being defined as a command-line parameter in the compiler invocation).

You need to also be aware than some implementations may define words which are likely to show up in a token-like fashion in a file path. For example, GCC may define macros with names like unix and linux unless it is invoked with an explicit C standard (which is not the default). That could be triggered by paths like platform/linux/my-header.h or even linux-specific/my-header.h.

To avoid these issues, I'd recommend that if you use this hack:

  • you use a C (or C11) standards-conformant compiler setting, and

  • you place the sequence very early in your source file, ideally before including any other header, or at least any header outside of the standard library.

Also, you wouldn't need the complication of the IDENT macro if you could write the concatenation without spaces. For example:

#define XSTR(x) #x
#define STR(x) XSTR(x)

#define Dir sys
#define File socket.h

#include STR(Dir/File)


Notes

  1. I tried it with clang, gcc and icc, as available on godbolt. I don't know if it works with Visual Studio.

  2. More accurately, it semi-respects whitespace: whitespace is converted to a single space character.



Related Topics



Leave a reply



Submit