1

I wrote a function that prints text on standard output. At compilation (using gcc exemple.c), i get a warning : implicit declaration of function 'write'. Here is an exemple :

exemple.c :

#include <unistd.h>

int main(void){
    write(1, "Hello World !", 13);

    return (0);
}

Output :

exemple.c: In function ‘main’:
exemple.c:4:2: warning: implicit declaration of function ‘write’ [-Wimplicit-function-declaration]
  write(1, "Hello World !", 13);

I included the unistd.h header, that's why i don't understand the reason of the warning.

I managed to "fix" the warning by adding

#include <sys/types.h>
//The real prototype, from unistd.h
extern ssize_t write(int __fd, void *__buf, size_t __n)__wur;

But this tells me it may be a bad idea.

Shouldn't the unistd.h be enought like in these exemples ? Or is there a better way to use/compile write ?

Note : I'm compiling with the gcc 5.3.1

Edit : Here is the link to the .i file created by running gcc exemple.c -save-temps : exemple.i

Hollyol
  • 827
  • 1
  • 13
  • 25
  • 3
    Try running `gcc -E exemple.c` and look at the paths printed there. It is likely that some *other* `unistd.h` is picked up, and not the right one. – Florian Weimer Nov 05 '17 at 21:05
  • 1
    Your test program compiles without complaint for me on a very similar computer, and I know from extensive experience with POSIX that it _should_ compile without complaint. The most likely explanation is that you have a broken C library installation. Please run your compilation again using the _exact same_ compiler command line but adding `-save-temps` to the end; this will create a file named `exemple.i`. Upload that file somewhere we can see it, and edit the URL into your question. (It will be much too long to post directly.) – zwol Nov 05 '17 at 21:07
  • 1
    Using `-std=c11` suppresses non-standard function declarations. Use `-std=gnu11` or request POSIX and X/Open extensions with `#define __XOPEN_SOURCE 700` or equivalent before you include any system headers. – Jonathan Leffler Nov 05 '17 at 21:12
  • @Florian Weimer - indeed, the path used is not the one i expected – Hollyol Nov 05 '17 at 21:12
  • @JonathanLeffler I thought that might be the problem too, but even in `-std=c89` mode with no feature-selection `#define`s, glibc gives anyone who includes `unistd.h` at least what was in that header in POSIX.1-1990 (which includes `write`). – zwol Nov 05 '17 at 21:43
  • @zwol - I uploaded the file – Hollyol Nov 05 '17 at 21:48
  • 2
    @Hollyol OK, so you have a file named `/usr/local/include/unistd.h`, and the compiler is picking up that file instead of the correct `/usr/include/unistd.h`. The question is now _why_ you have that file, and what else you might have in `/usr/local/include` that could interfere with the C library. (That directory is supposed to be for third-party library headers, not for headers that mask the real C library.) Please show us the output of `ls -l /usr/local/include`. – zwol Nov 05 '17 at 21:51
  • @zwol - there is nothing else in `/usr/local/include`, only unistd.h – Hollyol Nov 05 '17 at 21:55
  • 1
    `/usr/local/include` should not even be on the default include path, unless you are using a custom build of gcc that is prefixed to `/usr/local` ... maybe you could give some background here (e.g. did you in fact build gcc yourself) – M.M Nov 05 '17 at 21:57
  • @M.M - No, i don't remember changing anything with gcc, and i didn't build it myself either :/ – Hollyol Nov 05 '17 at 22:05
  • @Hollyol I still want to see the output of `ls -l /usr/local/include`, **unedited**. Actually, make that `ls -la /usr/local /usr/local/include`. – zwol Nov 05 '17 at 22:48
  • 2
    @M.M. Au contraire, `/usr/local/include` is always on gcc's default include path, because even if $prefix is something else you probably want to pick up locally-installed third-party libraries. (This design decision was made in the 1990s, maybe even the 1980s, and I could see an argument that it's wrong nowadays.) – zwol Nov 05 '17 at 22:49
  • "I'm using Linux 4.4.16-21-generic x86-64" -- That's the version of your kernel, and it's not likely to be relevant. Are there any comments at the top of your `/usr/local/include/unistd.h`? – Keith Thompson Nov 05 '17 at 22:49
  • @zwol - Here it is : `total 4` `-rw-r--r-- 1 root root 157 Aug 19 2016 unistd.h` – Hollyol Nov 05 '17 at 22:56
  • @KeithThompson - It says `Includes machine specific syscall numbers`, actually, the only thing it does is including `` – Hollyol Nov 05 '17 at 23:01
  • I fixed the issue by setting the environement variable : `C_INCLUDE_PATH=/usr/include` in order that this directory will be browse before `usr/local/include`, like suggested here - http://www.network-theory.co.uk/docs/gccintro/gccintro_23.html – Hollyol Nov 05 '17 at 23:07
  • @Hollyol So I think what you've got here is someone copied `linux/unistd.h` into `/usr/local/include`. I haven't got the foggiest idea why anyone would do that, and, as you have seen, it breaks compilation of ordinary programs. Is this your personal computer or is it administered by someone else? Does anyone else have access to it? Do you remember what you were doing on August 19, 2016? Do you remember messing around with header files at any point? – zwol Nov 05 '17 at 23:08
  • @zwol - This is my personal computer, and i don't remember playing with headers, but i may have done it anyway. – Hollyol Nov 05 '17 at 23:19
  • @Hollyol Well, I think you can probably just go ahead and delete the `unistd.h` in `/usr/local/include`, but if you ever find out how it got there and why, I would love to know. – zwol Nov 05 '17 at 23:25
  • On a dpkg based system you can try `dpkg -S /usr/local/include/unistd.h` to try to find if a package installed this file. – Julien Palard Nov 05 '17 at 23:27
  • @zwol - Removing the file fixes the warning, thanks ! – Hollyol Nov 05 '17 at 23:39

0 Answers0