special character in #define macro - c++

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.

Related

Using macro with string fails on VC 2015

Why does this fail to compile?
char programDate[] = "("__DATE__")";
But this compiles fine (see space):
char programDate[] = "(" __DATE__")";
I do know VC2015 now supports literal-operators. But shouldn't that be in compilation phase? __DATE__ should have been processed by the pre-processor. What is going on here?
I thought of some mix-match issue with Unicode/non-Unicode build - but it doesn't help. It's not just issue with pre-defined macros, but with user defined also:
#define MACRO "abc"
char data[] = "("MACRO")";
EDIT:
Error C3688 invalid literal suffix '__DATE__'; literal operator or literal operator template 'operator ""__DATE__' not found
Since C++11, user-defined literals exist and are part of preprocessing. The grammar is:
preprocessing-token:
user-defined-string-literal
// other stuff...
user-defined-string-literal:
string_literal ud-suffix
ud-suffix:
identifier
So "("__DATE__ matches preprocessing-token, but "(" __DATE__ doesn't (that is two separate preprocessing tokens).
Macro replacement happens after tokenization. Since there is no token __DATE__ in your first example, there is no replacement.

Is it possible to define another preprocessor directive?

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.

Error checking through 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.

Why does the C++ compiler give errors after lines instead of on them?

This question popped into my head today at work when I was having yet another domestic affair with my compiler. Despite my buff pinky (due to all the semicolon pressing I do at work), I managed to miss one before an if statement. Obviously, this resulted in a compile error:
error C2143: syntax error : missing ';' before 'if'
So I wondered "well gee, why can't you tell me the line that's missing the semicolon instead of the line after the problem." and I proceeded to experiment with other similar syntax errors:
error C2065: 'myUndeclared' : undeclared identifier
error C2143: syntax error : missing ')' before 'if'
etc...
Now, all of those errors would, similarly, take me to the line after the problem and complain about something before the if statement.
Consider the following:
SomeFunction(x) //Notice, there is no ';' here
if(bSomeCondition)
{
...
}
I get two compile errors:
(Line 265) error C2065: 'x' : undeclared identifier
(Line 266) error C2143: syntax error : missing ';' before 'if'
However, the first error correctly tells me the line number, despite the missing semicolon. This suggests to me that the compiler doesn't get tripped up in parsing and is able to make it past the semicolon problem. So, why is it that the compiler insists on grammatical errors being reported in this way? Other errors (non grammatical) are reported on the lines they are found. Does this have to do with the compiler making multiple passes? Basically, I hope someone with a working knowledge of the C++ compiler might explain specifically what the compiler is doing that necessitates the reporting of errors in this "before" way.
The short answer to the more general question of "Why do C/C++ error messages suck" is "Sometimes C++ is really hard to parse" (it doesn't actually have a context free grammar). However, this isn't really a valid reason - one can still make tools that record better diagnostic information than most C++ compilers.
The more practical answer is "Compiler authors have inherited legacy codebases which didn't value error messages", combined with a mild dose of "compiler authors are lazy", topped with "Diagnostic reporting isn't an exciting problem". Most compiler writers would add a new language feature or 3% codegen performance improvement, rather than do significant refactoring on the codebase to allow decent error reporting. The specific question about "Why aren't errors properly localised to the line that 'caused' them" is an instance of this. There's not really a technical reason compilers can't generally work out that a ; is missing
, and then tell you about the source span of the last ; lacking statement - even in the presence of C++'s general whitespace invariance. It's just that storing that information has (largely) been historically ignored.
That said, new compilers not hampered by decades of old code are doing much better. Have a look at the Clang compiler, which prides itself on sensible error messages. The page on diagnostics shows how much better than GCC they are. An example for this case being:
$ gcc-4.2 t.c
t.c: In function 'foo':
t.c:5: error: expected ';' before '}' token
$ clang t.c
t.c:4:8: error: expected ';' after expression
bar()
^
;
Or, more impressively:
$ cat t.cc
template<class T>
class a {}
class temp {};
a<temp> b;
struct b {
}
$ gcc-4.2 t.cc
t.cc:3: error: multiple types in one declaration
t.cc:4: error: non-template type 'a' used as a template
t.cc:4: error: invalid type in declaration before ';' token
t.cc:6: error: expected unqualified-id at end of input
$ clang t.cc
t.cc:2:11: error: expected ';' after class
class a {}
^
;
t.cc:6:2: error: expected ';' after struct
}
^
;
Look, it's even telling us what to type where to fix the problem! </clang_salespitch>
Because in C++, white-space doesn't matter, on the whole. So this is valid code:
SomeFunction(x)
;if(bSomeCondition)
{
...
}
So the compiler message is simply reporting that a semi-colon hasn't appeared somewhere before the if.
In this code:
SomeFunction(x)
if (y) {
}
As you said, the error would be reported on line 2 as missing ';' before 'if'.
There is not wrong with line 1. It's perfectly valid without a semi-colon, and several expressions are possible besides just a semi-colon (such as a dot, or a math operator, or assignment, or a pointer, etc).
So, reporting the error on the previous line may not always make sense, take this example:
SomeFunction(x)
+= 10
- 5
// blank line
// blank line
if (y) {
}
Which line has the error? The line with the - 5? Or one of the comment lines? To the compiler, the error is actually with the 'if', since it is the first place that something can be detected as being wrong. To report a different line, the compiler would have to report the last properly parsed token as the error, rather than the first place the error is detected. That sounds a little backwards, and saying that //blank line1 is missing a semi-colon is even more confusing, since changing it to //blank line; would of course not change or fix the error.
By the way, this is not unique to C or C++. This is a common way to report errors in most parsers.
Quite simply, because of how parsing is done. When the parser expects ;, and instead encounters if, the error is in the if. The simplest sane way to report it is to say ; was expected before if.
The compiler is white space agnostic. It doesn't know (or care) that there is a carriage return or tabs or spaces in between your statements. all it cares about is what is after or before semi colons, or after/before brackets ('{','}') which end and begin classes and functions. That's why :)
Because when it's done parsing that line it does not know that you wanted a semicolon there yet. Let's look at an example:
int mystuff
Is this line missing a semicolon? That depends on what comes next. For instance the following construct is perfectly ok:
int mystuff
= 1;
I would never write it like that, but for the compiler it is ok.
Because, the following code would be correct:
SomeFunction(x)
;if(bSomeCondition)
{
}
That's because unecessary whitespaces are ignored.
The short answer: you can put ; into line 266, and then it's going to be fine. From the compiler's perspective the error is there.
You might want to try clang, although I don't know whether it gives better error message for this particular type of error but in general it gives a lot clearer error messages.
It is because compiler checks for 1 whole statement. Let me give an example:
int a,b,c
c=a+b;
cout<<c;
This code generates compilation error, that "; is expected before c/line 2", this happens because compiler first looks at line 1's int a,b,c and the compiler has no clue whether there will be any other variable or statement and so the compiler moves to second line(because whitespaces are allowed), and then it sees that there is "c=a+b", which is a statement, and thus compiler knows that something is wrong, as it was expecting either a variable or a semicolon(;). And so, it tells us that it was expecting a ; before a statement.
So long story short, compiler doesn't look for a semicolon after a statement(if that was the case we might not be able to use whitespaces in our codes), it looks for ; right before the other statement, because compiler has no clue how long the first statement would be.

How can I work around Visual C++ 2005's "decorated name length exceeded, name was truncated" warning?

For example, say for some reason I had a piece of code that looked like this:
mutable std::vector<std::vector<std::vector<std::vector<
std::vector<MyNamespace::MyType> > > > > myFreakingLongVectorThing;
and I am getting a warning that looks like this:
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include\xstring(1665) : warning
C4503: 'std::vector<_Ty>::operator []' : decorated name length exceeded, name was truncated
with
[
_Ty=std::vector<std::vector<std::vector<std::vector<std::vector<MyNamespace::MyType>>>>>
]
is there any way I could rewrite that freaking long vector thing to not get that warning? I still want the data structure to be the same, but not get that warning. I don't want to disable the warning. Possible?
Note: This is Visual Studio 2005
....if you're really curious about why I'm working with such a hideous data structure, it's caused by auto-generated code.
If you don't want to see the warning you either have to disable it or use a newer compiler.
The warning is about debug information being limited to 255 characters for the type name. As long as these 255 characters are not identical for two different types, you are ok. And if they are identical, you cannot do much about it anyway!
Just turn it off until you can upgrade the compiler!
This isn't all that different from the error I used to get in Visual C++ 6 anytime I did just about anything with STL maps. You simply need to bite the bullet and tell the compiler to shut up about that warning. It's got a fundamental internal limit on how long a type name can be. As it is, it's a pretty useless warning, just complaining about the compiler/debugger's internal name limit.
#pragma warning(disable : 4503)
And if you're thinking at all about porting to another compiler, just wrap it in a #ifdef for Visaul C++:
#ifdef MSVC
#pragma warning(disable : 4503)
#endif