Why assert is causing compilation error if I use it before main() call? It causes compilation error (Syntax error):
test.cpp:4:8: error: expected ')' before numeric constant
Note: I'm trying to understand why I'm a getting a syntax error for calling it outside main. That too related to something like "numeric constant", but not like function / macro called out side main function. If the error was simpler like function / macro called out side main, then my question wouldn't have made any sense.
#include <stdio.h>
#include <assert.h>
assert(0); //If I comment assert from here, then it compiles fine.
int main()
{
assert(0);
return 0;
}
Since all the other answers are "it didn't work because you can't do that", here's one that dives in to why the error message looks the way it does.
The short reason is compilers aren't smart, and they don't make good teachers.
When we, the experienced human programmers, look at this code
assert(0);
int main(void){}
we recognize the first line as an attempt to call a function, and use that as the starting point of an explanation about why it's invalid and what you should have written instead. There's a bit of mind-reading involved in the recognition of your intent, because you expressed that intent with incorrect code.
The compiler can't read your mind, and by definition the only way it can recognize your intent is if your code is valid. Since it doesn't understand what you're trying to do, it can't give helpful advice.
What the compiler is actually doing is just taking in your code, one token at a time, and parsing it according to a grammar. If the code is ungrammatical, there will be a point at which the next token doesn't match any grammar rules. The compiler then tells you what the offending token was. In this case the offending token was the numeric constant 0
.
The tokens preceding the 0
were parsed without complaint, but that doesn't mean they were interpreted the way you intended them.
It's hard to completely analyze this specific case because <assert.h>
declares assert
as a macro, and I don't know what it expands to on your system. To make the explanation a little easier, let's use a normal function:
/* sample program 1 */
foo(0);
int main(void){}
The above code fails to compile. My compiler says
error: expected declaration specifiers or '...' before numeric constant
But this slightly altered version:
/* sample program 2 */
foo();
int main(void){}
compiles with only some warnings, because in old-style C, the first line is a valid declaration of a function foo
, using the implicit int
return type! If my intent was to somehow "call foo
before main" then it's a total failure. If my intent was to only declare foo
then I'm only guilty of using an obsolete language feature.
Now, knowing about the second sample, look back at the first sample. When the compiler reads the first 2 tokens, foo
and (
, everything is fine. The program still fits the grammar of (old-fashioned) C. Then it gets to the 0
and there's no way to proceed. So it tells me that the numeric constant is the problem.
Now what about those things it says it was "expecting"? Those are the tokens that can come next in a valid program. It suggests a declaration specifier list rather than an immediate )
, because this is valid too:
foo(int);
int main(){}
Even this, using an old-style function definition, would be a possible continuation:
foo(i)
int i;
{
}
int main(){}
Bottom line: whenever there's a parse error, the compiler reports the point where your program diverged grammatically from the set of all possible valid programs. The point where the parse diverged semantically from your intent is sometimes earlier. Sometimes a lot earlier. In that case, the compiler's "expected" tokens can be quite irrelevant.