I've been looking through code golf and got an idea to try this code:
#define D #define after adding this line, everything worked fine, however I expanded it into this:
#define D #define
D VALUE
And here I got 5 compilation error. If I change D into #define everything is fine, can someone explain, why this code is illegal?
NOTE: I used VS2008 compiler.
EDIT: After some answers I see that I needed to give compilations error list:
error C2121: '#' : invalid character : possibly the result of a macro expansion
error C2146: syntax error : missing ';' before identifier 'VALUE'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2144: syntax error : 'void' should be preceded by ';'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
First error shows that D is not just define but also includes #.
C 2011 (N1570) 6.10.3.4 3: “The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one,…”
C++ 2010 (N3092) 16.3.4 [cpp.rescan] 3 has exactly the same text.
This code is illegal because language specification says it is illegal. According to C and C++ preprocessor specification, whatever code you build using preprocessor will never be interpreted as another preprocessor directive. In short, you cannot build preprocessor directives using preprocessor. Period.
(Also, you cannot build comments using preprocessor.)
It does look like your preprocessor is making the substitution you want, but you likely wouldn't get the behaviour you want - the preprocessor is normally just a single pass operation. Example (with clang, but you should be able to reproduce by using the appropriate VS2008 flags):
$ cat example.c
#define D #define
D VALUE
$ cc -P -E example.c
#define VALUE
That #define VALUE is going straight through to the compiler, which won't know what to do with it - it's a preprocessor directive, after all. Clang's error, for reference, is similar to yours:
$ cc -c example.c
example.c:2:1: error: expected identifier or '('
D VALUE
^
example.c:1:11: note: expanded from macro 'D'
#define D #define
^
1 error generated.
That won't work because preprocessing is performed in a single pass. For example, consider the next code :
#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6
int main() {
return 0;
}
After preprocessing, your code will looks like :
#define N 6
int main() {
return 0;
}
and "#define" is not a valid syntax on C or C++. Also, since the resulting preprocessor directive is not going to be processed, it won't resolve subsequent references to the "N" macro in your code.
Just for fun, you can call the preprocesor twice from the command line using g++/gcc. Consider the next code (define.cpp) :
#include <iostream>
#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6
using namespace std;
int main() {
cout << N << endl;
return 0;
}
Then you can do:
$ g++ -E define.cpp | g++ -o define -x c++ - && ./define
and will output:
6
Lines of code in the pre-processors eyes are either pre-processor statements (And thus don't have any replacements done on them) or normal text statements (And have replacements done). You can't have one be both, so once you have 'D' be replaced it's only going to look to see if there are any more macros to replace. Since there are none, it just leaves '#define' in the C++ code as it is and then the C++ compiler will error when it sees it (Since '#define' isn't valid C++ code).
So show my point more, this is invalid code for the pre-processor:
#define D define
#D value
Because the pre-processor doesn't do any macro replacement on pre-processor statements, and "#D" isn't a recognized pre-processor command. And this:
#define D #define
D value
Results in this C++ code:
#define value
Which is invalid because the pre-processor is already done being run.
Looking at the grammar in 16 [cpp] paragraph 1, a replacement-list consists of pp-tokens which may include the production # no-directive which is described in paragraph 2 of the same paragraph as
A non-directive shall not begin with any of the directive names appearing in the list.
That is, something of the form
#define NAME # define
happens to be illegal! Also note that the # in this context does not turn the next word into a string: the quoting following a # only happens shen the # is immediately followed by a macro parameter name in a function-style macro.
Related
I have these macros defined for visual studio and clang and they both compile fine
#if defined(_MSC_VER)
# define _declare_func(...) PP_CAT(PP_CAT(_declare_func_, PP_NARG(__VA_ARGS__)),(__VA_ARGS__))
# define declare_func(...) _declare_func PP_LEFT_PAREN notused,##__VA_ARGS__ PP_RIGHT_PAREN
#else // clang version
# define _declare_func(...) PP_CAT(_declare_func_, PP_NARG(__VA_ARGS__))(__VA_ARGS__)
# define declare_func(...) _declare_func ( notused,##__VA_ARGS__ )
#endif
#define _declare_func_1(notused) void my_function()
#define _declare_func_2(notused, scope) void scope::my_function()
class MyClass
{
declare_func();
};
declare_func(MyClass) { }
PP_CAT is a classic multilevel concat macro
PP_NARG counts the number of macro arguments
PP_LEFT_PAREN and PP_RIGHT_PAREN reduce to '(' and ')'
Is there any way to achieve this with GCC ? ( I tried both macro version with GCC 5.2, both fail to compile because the comma seem to be propagated during macro resolution and removed only at the end of preprocessing, making PP_NARG always reduce to '2' and never '1')
Thanks !
From doc:
Second, the ‘##’ token paste operator has a special meaning when placed between a comma and a variable argument. If you write
#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)
and the variable argument is left out when the eprintf macro is used, then the comma before the ‘##’ will be deleted. This does not happen if you pass an empty argument, nor does it happen if the token preceding ‘##’ is anything other than a comma.
eprintf ("success!\n")
==> fprintf(stderr, "success!\n");
The above explanation is ambiguous about the case where the only macro parameter is a variable arguments parameter, as it is meaningless to try to distinguish whether no argument at all is an empty argument or a missing argument. In this case the C99 standard is clear that the comma must remain, however the existing GCC extension used to swallow the comma. So CPP retains the comma when conforming to a specific C standard, and drops it otherwise.
So for
#define declare_func(...) _declare_func ( notused,##__VA_ARGS__ )
the comma remain in C standard, you may use -std=gnu99 or -std=gnu++11 to drop the comma and have your working macro.
Demo
To make your macro works with -std=c++11, you have so to force to have at least one argument.
#define DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__[0, 2] 1
warning: missing whitespace after the macro name [enabled by default]
I was trying to compile a third party header file and gcc is throwing this warning.
I am not sure what this macro does. Is it a shortcut for defining the following ? How do I fix the warning ?
#define DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__0 1
#define DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__1 1
#define DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__2 1
#define DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__[0, 2] 1
In C89/C90, this is a valid macro definition, but there's nothing special about the [ and ] characters. It defined an object-like macro called DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__, and the definition is equivalent to:
#define DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__ [ 0 , 2] 1
so that any use of DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__ expands to [0, 2] 1. (That's not even likely to make sense; C doesn't permit multiple index expressions within [...], and 0, 2 is going to be interpreted as a comma expression equivalent to just 2.)
C99 added a new rule (6.10.3p3):
There shall be white-space between the identifier and the replacement list in the definition
of an object-like macro.
which makes the above definition invalid (a constraint violation requiring a diagnostic). Adding a space after the macro name:
#define DF__TCDX0_RB_INFO__BRANCH_INDEX_LIST__ [0, 2] 1
would silence the warning, but that's unlikely to be the correct fix.
It looks like the intent is to permit uses of the macro to use [ and ] for some special purpose, but that's not something the standard language supports. It might be a compiler-specific extension, but it's not one I've ever encountered, and I probably wouldn't recommend using it.
It might be useful to see some code that refers to the macro.
I want to compile a time error checking as mentioned below . But I am not able to find out how to use it inside main()?
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
int main(){
BUILD_BUG_ON_NULL(12);
}
Below is the mentioned error
1--error C2332: 'struct' : missing tag name
2--error C2143: syntax error : missing ')' before '{'
3--error C2027: use of undefined type 'main::<unnamed-tag>'
4--error C2143: syntax error : missing ';' before '{'
5--error C2059: syntax error : ')'
Can anyone please let me know what I am doing wrong?
EDIT: the question was originally tagged as C++, but now as just C.
I'm not going to chase further fundamental changes of the question.
Original answer for the C++ tagged question:
This source code:
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
int main(){
BUILD_BUG_ON_NULL(0);
}
compiled with g++ 4.7.1., produced
foo.cpp: In function 'int main()':
foo.cpp:4:1: error: types may not be defined in 'sizeof' expressions
foo.cpp:4:21: warning: statement has no effect [-Wunused-value]
Which says directly what’s wrong.
So it is a good idea to compile with different compilers.
Possibly you’re looking for compile time assertions.
With C++11 you can use static_assert, e.g. via a macro such as
#define STATIC_ASSERT( e ) static_assert( e, #e )
In C++03 you could implement it as a valid/invalid typedef, because a typedef can be repeated in the same translation unit, and can be used in a class definition:
#define STATIC_ASSERT( e ) typedef char staticAssert_shouldBeTrue[e? 1 : -1]
One problem with that was that g++ had/has a compiler bug, where a repeated typedef is not always accepted as it should be, necessitating generation of a locally unique name for each one, e.g. by using __LINE__.
But you can always just use the definition in the Boost library, since Boost supports most extant compilers with special-casing for each one as necessary.
First the macros BUILD_BUG_ON_ZERO and BUILD_BUG_ON_NULL trigger a compilation error if their argument is different than 0.
If the macro argument is 0, they will not trigger any compilation error but yield a 0 for BUILD_BUG_ON_ZERO and a (void *) 0 for BUILD_BUG_ON_NULL
These macros comes from the Linux kernel which is written in C and they are only working for C programs.
In C++ these macros are not working. The reason is in C++ you cannot declare a structure in a sizeof expression.
You don't mention in your question if you are compiling your program in C or in C++, but I strongly suspect you are compiling it in C++. So don't use these macros in C++.
Compiling with gcc -std=c99 -pedantic-errors, I get
screwed.c: In function ‘main’:
screwed.c:5:1: error: negative width in bit-field ‘<anonymous>’
screwed.c:5:1: error: struct has no named members [-pedantic]
and those are the errors the compilation should give when the code is compiled as C. The width of a bit-field must be non-negative (positive if it has a name), and a struct must have at least one named member (two, if the last one is a flexible array member). structs without tags are allowed.
You either compiled the code not as C, or your compiler is non-conforming.
When compiling as C++, the additional error
error: types may not be defined in ‘sizeof’ expressions
is generated (but the one about the struct without named members disappears).
In C++, you may not define type in a sizeof expression, and your compiler chose a less clear way of telling you.
I am new to C++ and facing one easy problem mention below.
in visual C++ 2008, i am trying to #define something like
#define fromThis* toThisPtr
#define fromThis toThisObj
I am porting some code that is written in linux and need to port in accordance to winapi. The error which i am getting
something like this.
error C2008: '*' : unexpected in macro definition
warning C4005: 'fromThis' : macro redefinition
see previous definition of 'fromThis'
I need to redefine fromThis* and fromThis during preprocessing time. Is special character in #define macro are not allowed?
How can i work this code out?
EDIT-1:
I am looking out possible solution to this. I am trying to repalce *fromThis to 'toThisPtr'. One suggested solution is use of typedefs. Which i did like below.
typedef toThisPtr fromThis*;
typedef toThisObj fromThis;
Now with this solution the error which i am getting is this:
error C2143: syntax error : missing ';' before '*'
error C2059: syntax error : ';'
error C2040: 'iovec' : 'toThisObj' differs in levels of indirection from 'toThisPtr'
can typedef be the siolution to this problem. What are the std way to replace fromThis* to change into toThisPtr?
The documentation for #define says its first argument is an identifier. Identifiers can only contain letters, digits and underscores and must not start with a digit.
Therefore, fromThis* is not a valid identifier, and you cannot #define it to something else.
You can't really do that, nor should you. :)
For this, I'd personally use typedefs instead of macros.
typedef toThisPtr fromThis*
typedef toThisObj fromThis
and then just do a replace all.
Perhaps you've just got it backwards
#define toThisPtr fromThis*
#define toThisObj fromThis
This defines two macros called toThisPtr and toThisObj. Otherwise I've having a really hard time understanding what you are trying to do.
You can not use * in a name.
See the excerpt from the documentation:
You may define any valid identifier as a macro, even if it is a C
keyword
A valid identifier is a sequence of one or more letters, digits or
underscore characters (_). Neither spaces nor punctuation marks or
symbols can be part of an identifier. Only letters, digits and single
underscore characters are valid. In addition, variable identifiers
always have to begin with a letter.
The following example compiles (VS2010 C++ compiler issues a warning C4353 though) and expression (*) evaluates to 0:
#include <iostream>
#include <string>
int main()
{
0(1, "test"); // (*) - any number and type of arguments allowed
int n = 0(1, "test"); // 0
std::string str(0(1, "test")); // Debug assertion fails - 0 pointer passed
}
Is using 0 as a function name allowed/regulated by C++ standard or its resolution is compiler-specific? I was looking in the N3242 draft but could not find anything related to this. Microsoft compiler obviously resolves such construct (or one with __noop) as an integer with value 0.
warning C4353:
warning C4353: nonstandard extension used: constant 0 as function
expression. Use __noop function intrinsic instead
A function name is an identifier and an identifier needs to start with a non-digit (§2.11):
identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit
I don't know the answer, but I believe we can find it by a little googling...
Looking at the MSDN, I found two links:
C4353 : http://msdn.microsoft.com/en-us/library/2a68558f.aspx
__noop : http://msdn.microsoft.com/en-us/library/s6btaxcs.aspx
The second link explains the __noop
The __noop intrinsic specifies that a function should be ignored and the argument list be parsed but no code be generated for the arguments. It is intended for use in global debug functions that take a variable number of arguments.
Th example shows the __noop can be very interesting indeed for debug code:
#if DEBUG
#define PRINT printf_s
#else
#define PRINT __noop
#endif
int main() { PRINT("\nhello\n"); }
Another comment on the same page gives an historical hint on the 0 function:
The compiler converts the __noop intrinsic to 0 at compile time.
I guess that, once upon a time, this extension was called 0, not __noop, and that later, Microsoft created the __noop keyword because it was easier to search for, more readable, less "strange" than this 0 thing, and clearly marked as an extension (because of the two leading underscores, like MSVC's __declspec or gcc's __attribute__).
Conclusion: What about 0?
This is an extension (as per the warning message)
This is an historical, deprecated extension
Its use is deprecated in favor of __noop
It was deprecated at least at the VC++2003 time (if not before)