How can I expand or collapse the defines in the header file for example
#define IOC_IN 0x80000000
#define IOC_WS2 0x08000000
#define _WSAIOW(x,y)(IOC_IN|(x)|(y))
#define SIO_ASSOCIATE_HANDLE _WSAIOW(IOC_WS2,1)
I tried doing gcc -E file.h > output.h however this outputs an empty file. I am using MingW compiler.
I expect the defines to be subsituted like this:
#define IOC_IN 0x80000000
#define IOC_WS2 0x08000000
#define _WSAIOW(x,y)(IOC_IN|(x)|(y))
#define SIO_ASSOCIATE_HANDLE (IOC_IN|(IOC_WS2)|(1))
The defines "in the header" are not "expanded", what do you expect to happen?
Instead, places where they are used are going to be preprocessed to have the definitions inserted.
You typically preprocess a C file, not a header, i.e. something where a #define is used without being defined.
GCC (the preprocessor actually) ignores your defines because they are unused. Try appending int x = SIO_ASSOCIATE_HANDLE; and rerun the gcc.
Related
I'm having problems with cpp Preprocessor. I have this Input.h file like this:
#ifndef PLATFORM_MOBILE1111
#define MyTest WEB111
#endif
int MyTest;
I process it with this command (on OSX):
cpp -E -P Source/Input.h Generated/Output.h
I get this:
#define MyTest WEB111
int MyTest;
i.e. macro MyTest is not getting applied. Why?
After a bunch of experimentation, I found that if I insert an empty line, variable definition, a comment or any other line after #ifndef line - then it works fine.
#ifndef PLATFORM_MOBILE1111
#define MyTest WEB111
#endif
int MyTest;
So the input above gets processed correctly into:
int WEB111;
Can someone explain to me why that is happening? and how to solve that? Is there an option that I can pass?
Edit: I also found that ## (concatenation operator) doesn't work too!
Strange! You clearly found a bug in the clang preprocessor!
I can reproduce this as well (Apple LLVM version 8.1.0 (clang-802.0.42)) on OSX.
This also starts working as expected when you remove the spaces before #define (indentation), but leading spaces should not matter at all, and a lot of editors indent #defines inside #ifdefs.
One hint on what is going on is that in the bogus versions the #define is still present in the processed source code, while in the correct version it is not. So apparently the preprocessor did not recognize the #define as such at all.
Even this fails (note the leading space):
#define MyTest WEB111
int MyTest;
While this works as expected:
#define MyTest WEB111
int MyTest;
And this results in WEB222:
#define MyTest WEB111
#define MyTest WEB222
int MyTest;
While this results in WEB111:
#define MyTest WEB111
#define MyTest WEB222
int MyTest;
Crazy!1!! :-)
It seems that always the first indented #define gets ignored.
Now the 'solution': Use:
gcc -E Source/Input.cpp -P -o Generated/Output.cpp
This works as expected, although it is using the same LLVM.
So I assume the gcc executable initializes the preprocessor differently than the cpp. This is still a bug in cpp.
I found out that running preprocessor through c++ rather than cpp solves both of my problems:
c++ -E -P Source/Input.h Generated/Output.h
BTW.: you need to add -x c++ flag if you file is not using regular c/c++ extention for c++ command. cpp works fine without that.
I see this being done all the time for example in the Linux Kernel. What is the purpose of using the preprocessor commands vs just normal C++ if else block? Is there a speed advantage or something?
A preprocessor changes the C/C++ code before it gets compiled (hence pre processor).
Preprocessor ifs are evaluated at compile-time.
C/C++ ifs are evaluated at run-time.
You can do things that can't be done at run-time.
Adjust code for different platforms or different compilers:
#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */
#include <unistd.h>
#elif defined _WIN32 /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */
#include <windows.h>
#endif
Ensure header file definitions are included only once (equivalent of #pragma once, but more portable):
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Example { ... };
#endif
You can make things faster than at run-time.
void some_debug_function() {
#ifdef DEBUG
printf("Debug!\n");
#endif
}
Now, when compiling with DEBUG not defined (likely a command line parameter to your compiler), any calls to some_debug_function can be optimized away by the compiler.
Preprocessor is run before the compilation pass, so the compiler won't even see anything that was in the not-taken #if branch.
#if DEBUG
int a;
#else
double b;
#endif
gcc -c -DDEBUG=1 file.c will see "int a"
gcc -c file.c will see "double b"
Preprocessor allows you to actually cut out or paste in to your source file, code to be compiled. If its cut out, its gone, its like a comment, does nothing, is not compiled, produces no code in the binary. Devs will often use this technique to add code only in debug build for debugging purposes or for adding or excluding code for specific operating systems.
As per this answer, I tried printing a uint64_t, but it gives me an error:
error: expected ``)' before 'PRIu64'
Following is the minimal code showing what I am trying to do:
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <cstdio>
class X {
X() {
uint64_t foo = 0;
printf("%07" PRIu64 ": ", foo);
}
};
int main() {}
This minimal code compiles, but my actual code does not. However, I have tried with the 2 lines inside X::X() exactly the same in my actual code, and that does not work.
What should I look for to debug this further? My actual code also #includes other headers. Could that be causing the problem? Does order of including the headers matter?
Edit
PRIu64 is defined as follows on my machine:
# if __WORDSIZE == 64
# define __PRI64_PREFIX "l"
# define __PRIPTR_PREFIX "l"
# else
# define __PRI64_PREFIX "ll"
# define __PRIPTR_PREFIX
# endif
# define PRIu64 __PRI64_PREFIX "u"
In C++ the macros are not automatically defined just by including the file.
You need to add the following:
#define __STDC_FORMAT_MACROS 1
before
#include <inttypes.h>
How to printf uint64_t? Fails with: "spurious trailing ‘%’ in format"
One other possibility for this issue I just found in my own code is if another header already pulls in <inttypes.h> before you define __STDC_FORMAT_MACROS. For example:
Utils.h (Perhaps originally written for C, as it was in our case):
#include <inttypes.h>
// ... Function declarations
MyFile.cpp:
#include "Utils.h"
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
Since inttypes.h has already been included by Util.h, the compiler doesn't include it again, and doesn't see the declaration of __STDC_FORMAT_MACROS.
The solution is either to edit Utils.h to include #define __STDC_FORMAT_MACROS, or to make sure to define it before doing any includes in MyFile.cpp.
#define __STDC_FORMAT_MACROS
#include "Utils.h"
#include <inttypes.h>
The original setup actually compiled just fine on GCC 4.8 on Ubuntu, but failed with an old ltib GCC 4.3 toolchain for PowerPC, which made it all the more perplexing at first.
PRIu64 is not defined where you use it.
Replace it with the string "llu" and your code will compile (but that is not a fix, it just demonstrates the problem)
Maybe the include is missing. Maybe over zealos include guards and it being included without the magic token block the define. Maybe your pch is busted.
If you are on android JNI platform. Put this in your Android.mk:
LOCAL_CPPFLAGS := -D__STDC_FORMAT_MACROS
On a cross-platform project, I want to #include a header file whose name contains the name of the platform. I have a #define macro for the platform.
So for example, for
#define PLATFORM win32
I want
#include "engine\win32\devices_win32.h"
while for
#define PLATFORM linux
I want
#include "engine\linux\devices_linux.h"
I'm going with Richard Pennington's answer, minus one line of code - it works for me!
#define PLATFORM Linux
#define xstr(x) #x
#define str(x) xstr(x)
#define sub(x) x
#include str(sub(engine/PLATFORM/devices_)PLATFORM.h)
Usually, you would do something more like:
#ifdef WIN32
#include "devices_win32.h"
#endif
#ifdef LINUX
#include "devices_linux.h"
#endif
...rather than having a single PLATFORM definition which can be set differently depending on the platform.
#define PLATFORM Linux
#define xstr(x) #x
#define str(x) xstr(x)
#define sub(x) x
#define FILE str(sub(engine/PLATFORM/devices_)PLATFORM.h)
#include FILE
I'm not sure I'd use it, though. ;-)
I had to use Linux rather than linux because linux is defined as 1 in my compiler.
Well in practice, this could be achieved using something like
#define PLATFORM win32
#define INCLUDE_FILE devices_ ## PLATFORM
#define QUOTED_INCLUDE_FILE #INCLUDE_FILE
#include QUOTED_INCLUDE_FILE
but the the following rule would prevent you from doing this:
C comments and predefined macro names are not recognized inside a #include' directive in which the file name is delimited with <' and `>'.
C comments and predefined macro names are never recognized within a character or string constant. (Strictly speaking, this is the rule, not an exception, but it is worth noting here anyway.)
Please look at the following file: (it is a complete file)
#ifndef TEES_ALGORITHM_LIBRARY_WRAPPER_H
#define TEES_ALGORITHM_LIBRARY_WRAPPER_H
#ifdef _TEES_COMPILE_AS_LIB
#include <dfa\Includes\DFC_algorithms.hpp>
#include <DFA\FuzzyClassifier\FuzzyAlgorithmIntialization\InitFuzzyAlgorithm.hpp>
typedef teesalgorithm::tees_fuzzy_algorithms algorithms_switchyard_class;
#else
#include <DFA\Includes\commercial_algorithms.hpp>
//An incomplete class to hide implementation
class algorithms_switchyard_class;
#endif
class AlgorithmLibraryWrapper {
algorithms_switchyard_class * algorithmPtr_;
typedef teesalgorithm::tees_paramObj paramObj_type;
typedef teesalgorithm::tees_errorObj errorObj_type;
typedef teesalgorithm::tees_statusObj statusObj_type;
typedef teesalgorithm::tees_dataObj dataObj_type;
typedef teesalgorithm::tees_outputObj outputObj_type;
public:
AlgorithmLibraryWrapper(const std::string& sAlgName, paramObj_type& paramObj, errorObj_type& errObj, statusObj_type& statusObj, const char* sFilePath);
static bool dataReader(const std::string& sFileName, dataObj_type& dataObj, errorObj_type& errObj, statusObj_type& statusObj);
bool runalgorithm(const dataObj_type& dataObj, outputObj_type& outObj, errorObj_type& errObj, statusObj_type& statusObj);
~AlgorithmLibraryWrapper();
};
#ifdef _TEES_USE_COMPILED_ALGORITHM_LIB
# ifdef _MSC_VER
#if _MSC_VER < 1400 // If VC 2003
#ifdef _DEBUG
#error No AlgorithmLibWrapper libraries compiled for this version of VC
#else
#error No AlgorithmLibWrapper libraries compiled for this version of VC
#endif
#elif defined(UNDER_CE) // Win CE
#ifdef _DEBUG
#pragma comment( lib, "AlgorithmLibWrapperCEd" )
#else
#pragma comment( lib, "AlgorithmLibWrapperCE" )
#endif
#else // If VC 2005
#ifdef _DEBUG
#pragma comment( lib, "AlgorithmLibWrapperd" )
#else
#pragma comment( lib, "AlgorithmLibWrapper" )
#endif
#endif
#endif
#endif
#endif //TEES_ALGORITHM_LIBRARY_WRAPPER_H
I am getting the following errors; I don't know why. I manually counted the preprocessor directives also.
AlgorithmLibraryWrapper.hpp:10:1: unterminated #ifdef
AlgorithmLibraryWrapper.hpp:7:1: unterminated #ifndef
I am using the poor vxWorks gcc compiler. Please let me know if the fault is mine or the compiler's.
It could be that the problem is in the included files (if there actually are unbalaced #if/#endifs.
I would try preprocessing with another compiler. You can use gcc for that, doesn't matter it wouldn't compile. Just get gcc (or MinGW if you're on Windows) and run
cpp -Iinclude_direcories your_file
Or, if you don't like gcc, get MSVC Express edition. Again, you can preprocess code that even doesn't compile, so no problem with nonworking library etc.
Most compilers have an option that will give you the output from the preprocessor so you can check what it's doing. For example,
gcc -E file.c >file.preproc
will give you the pre-processed source so you can check the balancing of #if against #endif.
At a guess, one of the files you are #including from this one has a mismatched #ifdef/#endif pair. You need to look at all the files (as the preprocesor does), not just this one.
As others have noted, this is most likely due to mismatched include guards.
If the files you are including are under your control (i.e. not part of a 3rd party closed source library), you could consider replacing the #ifndef et. al. guards (which are used to prevent multiple inclusion) with #pragma once. This will eliminate the possibility of having mismatched preprocessor directives.
One caveat of this is that pragma once is non-standard, so it will only work if your compiler supports it.
I have tried to compile your source using vs 6.0 but did not get the error you have mentioned. As others said may be the error is coming from the included header file . For me to get your code compiled i need to comment the above header.
Please check the above header once.
I'd debug this by commenting out sections one by one and trying to identify which section is causing the error.
It could be your compiler does not like the nested #ifdefs or does not interpret the syntax correctly. Maybe it doesn't like the #pragmas.
This is a long shot, but in your source file you have the following line:
# ifdef _MSC_VER
where there is whitespace between the '#' character and the directive name (ifdef). This is valid in C/C++; however, it's not too commonly seen so I wouldn't be very surprised if the odd compiler choked on it.