I'm pretty sure there's such question, but I can't find it :\ Anyway, here's the issue:
What is the difference between开发者_开发知识库 wait
in stdlib.h
and sys/wait.h
o.O ?
In details - I just encountered this problem and I could't compile a simple C program. I isolated the problem and here's what I got:
#include <stdlib.h>
//#include <sys/wait.h>
int main()
{
int status;
wait( &status );
return 0;
}
If stdlib.h
is included, I got:
$ gcc asd.cpp
asd.cpp: In function ‘int main()’:
asd.cpp:9:16: error: conflicting declaration ‘wait& status’
asd.cpp:8:6: error: ‘status’ has a previous declaration as ‘int status’
What declaration ? O.o What is wait
here, that conflicts with int status
?
I found a thread in the net, where replacing stdlib.h
with sys/wait.h
solves the problem, but why is that and what is the difference?
EDIT: Thanks to sidyll's comment, I changed the file extention - from .cpp
to .c
and it worked! I'm shocked :) How is this so different? And still the same question - what is the different between those two wait
-s ?
The difference is that the wait()
in <sys/wait.h>
is the one you should use.
From the wait(3)
man page:
SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
The wait
function isn't defined by the ISO C standard, so a conforming C implementation isn't allowed to declare it in <stdlib.h>
(because it's legal for a program to use the name wait
for its own purposes). gcc with glibc apparently does so in its default non-conforming mode, but if you invoke it with gcc -ansi -pedantic
or gcc -std=c99 -pedantic
, it doesn't recognize the function name wait
or the type pid_t
.
I did gcc -E wait.cpp to dump the actual preprocessor expansions that take place. What I found was that on linux, the header /usr/include/bits/waitstatus.h
is included which pulls in a union wait { ... }
but the function wait() from sys/wait.h is never pulled in. The same thing happens with the c compilation, but the for whatever reason the compiler does not complain in that case.
To prove this to yourself, you can change your main to declare the wait as a variable rather than a function call, and the compiler will not complain:
int main() {
int status;
wait w;
return 0;
}
Note that GCC stands for GNU Compiler Collection, not GNU C Compiler (as many
other tools which were prefixed with a g). It's not a C-only compiler. And
many languages are detected by file extensions. Adam Rosenfield is partialy
correct in his comment. Yes, g++
will add the C++ library in the linker phase,
but that's not the unique difference (more on this later).
To explain how changing the extension solved it, please take a look in this text straight from GCC's manual:
Compiling C++ Programs
C++ source files conventionally use one of the suffixes
.C, .cc, .cpp,
.CPP, .c++, .cp,
or
.cxx;
C++ header files often use
.hh
or
.H;
and
preprocessed C++ files use the suffix .ii. GCC recognizes files with
these names and compiles them as C++ programs even if you call the
compiler the same way as for compiling C programs (usually with the
name
gcc).
So, "GCC regocnizes files with these names" and your program was being compiled
as C++ source. I guess that C++ has some special use of &
, which I can't tell
exactly (I don't know C++). Hence the error.
Now, regarding the difference between g++
and gcc
, continue with the next
paragraph:
However, the use of
gcc
does not add the C++ library.
g++
is a program
that calls GCC and treats
.c, .h
and
.i
files as C++ source files
instead of C source files unless
-x
is used, and automatically
specifies linking against the C++ library. This program is also useful
when precompiling a C header file with a
.h
extension for use in C++
compilations. On many systems,
g++
is also installed with the name
c++.
On the real question: there aren't two wait
s here in my system (Darwin 11), only
the standard syscall. Check if what Kevin said isn't happening. It's the same,
stdlib.h includes sys/wait.h:
#include <_types.h>
#if !defined(_ANSI_SOURCE)
#include <sys/wait.h>
#if (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
#include <alloca.h>
#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
#endif /* !_ANSI_SOURCE */
Check your header.
精彩评论