I have the below code in a larger C program. I've had no issues until just now when I tried to compile it; it's being run in Minix 2.0.4 and compiled using cc
. A compilation error is thrown as follows:
line 26: void not expected
Line 26 is simply a function declaration inside main()
:
void initpool(void);
initpool()
itself is defined later in the program with this header:
void
initpool(void)
{
From what I've researched everything should be correct, and gcc
throws no compilation errors. All previous lines do end with ;
s as they should, so that's not the issue. Why is cc
having a problem compiling it?
EDIT: As requested, the lines leading up to line 26 are as follows (starting at the beginning of main()
, line 25 is blank):
19: int
20: main(int argc, char *argv[])
21: {
22: int count, inserror;
23: olnode *list, *ptr;
24: list = NULL;
Most likely your program looks as follows:
int main(int argc, char ** argv) {
... // (a)
void initpool(void);
...
initpool();
...
}
The part denoted with (a) must contain some non-declaration statements. In older C compilers, declarations aren't allowed after the first non-declaration statement:
void foo() {
int a;
int b;
foo();
int c; // not allowed in old C
}
So, there are two possible fixes:
// the preferred fix for a single file
void initpool(void);
int main(int argc, char ** argv) {
... // (a)
...
initpool();
...
}
void initpool(void) {}
// the technically correct fix
int main(int argc, char ** argv) {
void initpool(void);
... // (a)
...
initpool();
...
}
The initpool
's forward declaration really doesn't belong inside main
. Why? Because you are supposed to let the compiler help you, and you shouldn't have to repeat yourself.
In terms of verbosity, the local declarations look outright silly:
// Good // Correct but Verbose
void initpool(void); void fun1(void) {
void fun1(void) { void initpool(void);
initpool(); initpool();
} }
void fun2(void) { void fun2(void) {
initpool(); void initpool(void);
} initpool();
}
Finally, suppose that initpool()
is implemented in a separate file. Then you're free to do whatever silliness you desire. For example:
// pool.c
void initpool(void) {
...
}
// main.c
int main() {
void initpool(); // a common typo
initpool(0); // undefined behavior, your hard drive gets formatted
}
You should have the public API of the pool component in a separate header file:
/// pool.h
void initpool(void);
/// pool.c
#include "pool.h"
void initpool(void) { ... }
/// main.c
#include "pool.h"
int main() {
initpool(); // OK
initpool(0); // the compiler will catch the mistake
}
Never mind that old compilers will gladly accept, for example, this:
void fun1() {
void initpool(int);
}
void fun2() {
void initpool(void);
}
Finally, it must be said that in C, and only in C (not C++), the following declarations are compatible, but that doesn't make it safe. The behavior is implementation defined. Such sloppiness will generate invalid assembly with stdcall, for example.
void bar(); // an unknown, fixed number of arguments
void bar(int,int,int,int);
The void bar()
is akin to void bar(...)
if C allowed such. Some old C compilers do indeed allow ellipsis without a preceding argument.
Thanks to Keith Thompson for forcing me to look deeper into things, and realizing how bad some compilers I use are :)