A different number of scans to expand the C preprocessor macro - c++

such a question below is a simple macro, however, the compilation behavior of msvc and gnu / clang is different, so to expand macro A in msvc, you need 1 scan more than gnu / clang, why is this happening?
#include <stdio.h>
#define EMPTY()
#define DEFER_(X) X EMPTY()
#define DEFER1(...) __VA_ARGS__ DEFER_(EMPTY)()
#define DEFER(...) __VA_ARGS__ DEFER_(EMPTY)()
#define TO_STR(X) TO_STR_(X)
#define TO_STR_(X) #X
#define A() 123
#define EXPAND(...) __VA_ARGS__
#define EXPAND1(...) EXPAND(__VA_ARGS__)
#define EXPAND2(...) EXPAND1(__VA_ARGS__)
int main(void)
{
printf(TO_STR(EXPAND1(DEFER(A)()))"\n");
}
The behavior for all compilers presented on godbolt is the same as gnu except msvc.

By default, MSVC does not use standard C or C++ rules for preprocessing. Use the switch /Zc:preprocessor to request standard-compliant preprocessing. You can also use /std:c17 to request conformance to the C standard generally, not just in preprocessing, although conformance may not be complete.

Related

define macro with conditional evaluation in C/C++

is there a way/trick to make a #define directive evaluate some condition?
for example
#define COM_TIME_DO(COND, BODY) \
#if (COND) BODY
#else
#endif
it's ok also to use template but body must be an arbitrary (correct in the context is used to) piece of code, simply just present or not in the source depending of COND.
as it is now the previous code doesn't even compile.
the goal of this question is primarly a better knowledge of the language and what i'm trying to do is define a debug macro system that i can activate selectively on certain parts of code for example:
A.hpp
#define A_TEST_1 1
#define A_TEST_2 0
Class A {
...
COM_TIME_DO(A_TEST_1,
void test_method_1();
)
COM_TIME_DO(A_TEST_2,
void test_method_2();
)
};
A.cpp
COM_TIME_DO(A_TEST_1,
void A::test_method_1() {
...
})
COM_TIME_DO(A_TEST_2,
void A::test_method_2() {
...
})
i was just asking if it was POSSIBLE because i like it more than the #if ... #endif.
If the expression of the condition will always expand to 1 or 0 (or some other known set of values) it is possible to implement such a macro.
#define VALUE_0(...)
#define VALUE_1(...) __VA_ARGS__
#define COM_TIME_DO_IN(A, ...) VALUE_##A(__VA_ARGS__)
#define COM_TIME_DO(A, ...) COM_TIME_DO_IN(A, __VA_ARGS__)
However, do not use such code in real life. Use #if and write clear, readable and maintainable code that is easy to understand for anyone.
is there a way/trick to make a #define directive evaluate some condition?
This depends on what the condition actually is.
Since you mentioned #if I'm assuming you'd like to evaluate an integer constant expressions.
Doing this in a macro single macro isn't possible, without implementation defined _Pragmas, but you can do it with an include + a macro definition:
#define COM_TIME_DO ((1 > 2), true, false)
#include "com-time-do.h"
// ^-- generates: false
#define COM_TIME_DO ((1 == 1), true_func();, false_func();)
#include "com-time-do.h"
// ^-- generates: true_func();
where com-time-do.h is defined as follows:
// com-time-do.h
#define SCAN(...) __VA_ARGS__
#define SLOT_AT_COND(a,b,c) a
#define SLOT_AT_THEN(a,b,c) b
#define SLOT_AT_ELSE(a,b,c) c
#if SCAN(SLOT_AT_COND COM_TIME_DO)
SCAN(SLOT_AT_THEN COM_TIME_DO)
#else
SCAN(SLOT_AT_ELSE COM_TIME_DO)
#endif
#undef COM_TIME_DO
Although, as KamilCuk said, please write reasonable code and don't use this.

Use #pragma pack with #define on Borland C++

I am trying to pack some structs with Borland C++Builder (XE6) (in the future: bcc).
I am using a library which uses the following construct to create structs:
#ifdef _MSC_VER
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#elif defined(__GNUC__)
#define PACKED_BEGIN
#define PACKED __attribute__((__packed__))
#define PACKED_END
#endif
PACKED_BEGIN
struct PACKED {
short someSampleShort;
char sampleByte;
int sampleInteger;
} structType_t;
PACKED_END
The bcc compiler does not like the MSC __pragma, and does not like preprocessor directives inside of macros although it is described on their website:
#define GETSTD #include <stdio.h>
My Question is: Is there any possibility to use this construct with the Borland Compiler for packing a struct without using:
#pragma pack(1)
to pack every struct?
Are there any workarounds for this?
As you stated, C++Builder does not support preprocessor statements inside of macros. This is documented on Embarcadero's site:
#define (C++)
After each individual macro expansion, a further scan is made of the newly expanded text. This allows for the possibility of nested macros: The expanded text can contain macro identifiers that are subject to replacement. However, if the macro expands into what looks like a preprocessing directive, the directive will not be recognized by the preprocessor.
The reason for that is because the # character inside of a macro is reserved for the preprocessor's stringizing operator.
Some compilers, including MSVC, get around that restriction with the __pragma() compiler extension, or the C99/C++x0 _Pragma() extension. C++Builder's Windows 32bit compiler does not support either of those. However, its Windows 64bit and mobile compilers (which are all based on clang and support C++11) DO support both of them. So you can add support for those compilers in the macros like this:
#if defined(__BORLANDC__)
#if defined(__clang__)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#else
#error Cannot define PACKED macros for this compiler
#endif
#elif defined(_MSC_VER)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#elif defined(__GNUC__)
#define PACKED_BEGIN
#define PACKED __attribute__((__packed__))
#define PACKED_END
#else
#error PACKED macros are not defined for this compiler
#endif
If you want to support the C++Builder Windows 32bit compiler, you will have to move the logic into .h files that use #pragma for it, and then you can #include those files where needed (at least until the compiler is updated to support clang/C++11 - which Embarcadero is currently working on):
pack1_begin.h:
#if defined(__BORLANDC__)
#define PACKED_BEGIN
#define PACKED
#define PACKED_END
#pragma pack(push, 1)
#elif defined(_MSC_VER)
#define PACKED_BEGIN __pragma(pack(push, 1))
#define PACKED
#define PACKED_END __pragma(pack(pop))
#elif defined(__GNUC__)
#define PACKED_BEGIN
#define PACKED __attribute__((__packed__))
#define PACKED_END
#else
#error PACKED macros are not defined for this compiler
#endif
pack_end.h:
#if defined(__BORLANDC__)
#pragma pack(pop)
#endif
Then you can do this:
#include "pack1_begin.h"
PACKED_BEGIN
struct PACKED {
short someSampleShort;
char sampleByte;
int sampleInteger;
} structType_t;
PACKED_END
#include "pack_end.h"
If you take this approach, you can just drop PACKED_BEGIN/PACKED_END altogether:
pack1_begin.h:
#if defined(__BORLANDC__) || defined(_MSC_VER)
#define PACKED
#pragma pack(push, 1)
#elif defined(__GNUC__)
#define PACKED __attribute__((__packed__))
#else
#error PACKED macro is not defined for this compiler
#endif
pack_end.h:
#if defined(__BORLANDC__) || defined(_MSC_VER)
#pragma pack(pop)
#endif
#include "pack1_begin.h"
struct PACKED {
short someSampleShort;
char sampleByte;
int sampleInteger;
} structType_t;
#include "pack_end.h"
The standard offers one extra alternative for writing pragmas: the _Pragma operator:
#define PACKED_BEGIN _Pragma("pack(push, 1)")
#define PACKED
#define PACKED_END _Pragma("pack(pop)")
If the Borland compiler supports it, it should work.

Is it possible to show the value of a #define at compile-time with ARM RVCT?

Question has been answered with VC and GCC in
How do I show the value of a #define at compile-time?
but is it possible to do it with ARM RVCT?
Actually I can do my own macro2string convertion as RVCT doesn't have stringification support. But I didn't even find "#pragma message" support in RVCT. It seems it has only something like
#pragma diag_error 223
which you must specify a tag, you can not freely output a string.
In fact I work on some legacy code now, here is an simplified example from the code base:
in product_conf.h:
#define VALUE_A 1
in platform_conf.h:
#ifndef VALUE_A
#define VALUE_A 2
#endif
in component_conf.h:
#ifndef VALUE_A
#define VALUE_A 3
#endif
in component.c:
#include product_conf.h
#include platform_conf.h
#include component_conf.h
It is a bit difficult to know VALUE_A is 1 or 2 or 3 when you are reading the component.c, actually in the real cases there can be 4~5 layers configurations and the c files may include or not include some certain conf.h, you have to go through the different header files case by case.
So I thought something like:
/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "=" VALUE(var[[)]]
#pragma message(VAR_NAME_VALUE(VALUE_A))
will help for a quick check, I just make the component and I will find out what is defined in the compiling output. This is doable with GCC, but I want to know how to do similar things with ARM RVCT.
or the only way to do it is:
#if (VALUE_A==1)
#warning "VALUE_A is 1"
#elif (VALUE_A==2)
#warning "VALUE_A is 2"
#elif (VALUE_A==3)
#warning "VALUE_A is 3"
#else
#error "VALUE_A is not properly defined!"
#endif

Is there widely-available wide-character variant of `__FILE__`?

One may generally use __LINE__ and __FILE__ in C++ programs, with many toolchains, including GCC.
__LINE__ under GCC evaluates to an expression of type int;
__FILE__ evaluates to a char const[N] where N is the appropriate value.
Does any major toolchain provide an equivalent to __FILE__ with type wchar const[N]?
If so, what is it?
You can make your own WFILE:
#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)
Tested with non-ASCII characters and filename 马克.cpp:
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)
int main() {
_setmode(_fileno(stdout), _O_U16TEXT); // required for Unicode output to console
wprintf(L"%s\n", WFILE);
}
Demo (running from cmd.exe and Chinese language support installed):
C:\>cl /W4 /nologo 马克.cpp
马克.cpp
C:\>马克.exe
马克.cpp
Use:
WIDE(MEXPAND(__FILE__))
and
WIDE(STRINGIFY(__LINE__))
or replace __LINE__ with anything that needs to be stringified, and replace __FILE__ with any macro string literal you want to widen.
Using the following definitions:
#define STRINGIFY2(m) #m
#define MEXPAND(m) m
#define STRINGIFY(m) STRINGIFY2(m)
#define WIDE(m) L ## m
Example usage:
#define AssertBreakMethod DebugBreak
#define AssertBreakForce(expr) \
do \
{ \
if (!(expr)) \
{ \
OutputDebugStringW(WIDE(MEXPAND(__FILE__)) \
WIDE("(") WIDE(STRINGIFY(__LINE__)) \
WIDE("): Assertion failed: ") \
WIDE(#expr) WIDE("\n")); \
AssertBreakMethod(); \
} \
} \
while (0)
Note that the whole parameter to OutputDebugString is assembled statically at compile time into a single string literal.
The trick with stringification of a macro is passing it through another macro. When __FILE__ is passed to MEXPAND it is expanded at that time. MEXPAND returns its argument which is now a string. It is then legal to put the leading L there to make it wide.
STRINGIFY does the same trick, it passes its argument through STRINGIFY2 which expands the argument to the line number (which looks like an integer at that point) then STRINGIFY2 puts the # symbol before it, stringifying the integer.
In Visual Studio just surround it with _T(), for example:
TRACE( _T("function = %s"), _T(__FUNCTION__);
I would have put this answer as a comment to an earlier reply but was not allowed due to not having the minimum 50 reputation to comment...
In Visual Studio, _T(__FILE__) will NOT expand to L__FILE__ unless you modify its standard definition of _T in the tchar.h header file. _T(__FILE__) and _T(__FUNCTION__) worked 5 years ago and still work today if you are looking for wide versions of the current file and function.
_T(x) is defined as __T(x), which is defined as L##x when _UNICODE is defined and x otherwise. So _T(__FILE__) expands to something like __T("my_file.c"), which then expands to L"my_file.c" or "my_file.c" depending on _UNICODE. It is useful to test things before claiming that they do not work.
For example use const auto name = L"" __FUNCTION__;

how to use #if,#else,#endif... inside c macro

#include < iostream >
#define MY_CHK_DEF(flag) \
#ifdef (flag) \
std::cout<<#flag<<std::endl; \
#else \
std::cout<<#flag<<" ,flag not define"<<std::endl; \
#endif
int main()
{
MY_CHK_DEF(FLAG_1);
MY_CHK_DEF(FLAG_2);
MY_CHK_DEF(FLAG_3);
...
}
complier report:
main.cpp:3:24: error: '#' is not followed by a macro parameter
any ideas?
Thanks
You can't do it. #if, #else, and #endif must be the first tokens on the logical line. Your definition is just one logical line, so it doesn't work,
You have to do it the other way round(defining the macro for each #if/#ifdef/#else condition(if you nest you have to put a definition on each branch). You probably should define it at every logical branch or it will fail to compile when you try to adjust a rarely adjusted flag. You can #define noops like this. Note to be careful not to wrap expressions with side effects into #define 'd macros that reduce to a noop when the debug flag is on, or your program may not work right.
#define N(x)
#include < iostream >
#ifdef (flag)
#define MY_CHK_DEF(flag)
std::cout<<#flag<<std::endl;
#else
#define MY_CHK_DEF(flag) \
std::cout<<#flag<<" ,flag not define"<<std::endl;
#endif
int main()
{
MY_CHK_DEF(FLAG_1);
MY_CHK_DEF(FLAG_2);
MY_CHK_DEF(FLAG_3);
...
}
C preprocessor is single-pass and #define creates a pretty dumb replacement that isn't further processed - your MY_CHK_DEF(flag) macro inserts the #if statement inline into preprocessed code that is interpreted by C compiler and not valid C.
You can either rephrase it to be one-pass, or if you can't, run through preprocessor twice, manually - once through cpp -P and the second time through normal compilation process.
You actually can do this if you use BOOST processor header lib.. it provides a BOOST_PP_IF macro allow this type of decisions.
http://www.boost.org/doc/libs/1_53_0/libs/preprocessor/doc/ref/if.html