C: Implicit declaration of function
Asked Answered
A

2

19

I am working on an assignment in which we are developing our own RPC client. Upon compiling my server portion, I receive warnings for the following:

implicit declaration of function 'read'
implicit declaration of function 'write'

I understand that I would typically receive this warning if I were to create a function following my main, ex:

int main() {
    doSomething();
}

void doSomething() {
    ...
}

In the above case, it should complain about the function that I created "doSomething".

Why then would my compiler complain that a system call was declared implicitly, when it appears in a function that was declared before the main? Below is the function in which the system call appears.

void Open(int connfd) {
/*Get message size*/
unsigned char temp[4] = { 0 };
int n = read(connfd, temp, 4);
if(n < 0) {/*On error*/
    perror("Read error");
    exit(1);
}/*End if*/
unsigned int msgSize = temp[0] +
    (temp[1] * 256) + 
    (temp[2] * 256 * 2) + 
    (temp[3] * 256 * 3);
printf("msgSize = %d\n", msgSize);

/*Allocate memory for message*/
char * msg = malloc(msgSize);
if(msg == NULL) {
    perror("Allocation error");
    exit(1);
}/*End if*/
msg = memset(msg, 0, msgSize);

/*Read entire message from client*/
n = read(connfd, msg, msgSize);
if(n < 0) {/*On error*/
    perror("Read error");
    exit(1);
}/*End if*/

/*Extract pathname from message - NULL terminated*/
char * pathname = malloc(strlen(msg) + 1);
if(pathname == NULL) {
    perror("Allocation error");
    exit(1);
}/*End if*/
pathname = memset(pathname, 0, strlen(msg) + 1);
pathname = memcpy(pathname, msg, strlen(msg));

/*Extract flags from message*/
int i;
for(i = 0; i < sizeof(int); i++) {
    temp[i] = msg[strlen(pathname) + 1 + i];
}/*End for i*/
unsigned int flags = temp[0] + 
    (temp[1] * 256) + 
    (temp[2] * 256 * 2) + 
    (temp[3] * 256 * 3);

/*Extract mode from message*/
for(i = 0; i < sizeof(mode_t); i++) {
    temp[i] = msg[strlen(pathname) + 1 + sizeof(int) + 1 + i];
}/*End for i*/
mode_t mode = temp[0] + 
    (temp[1] * 256) + 
    (temp[2] * 256 * 2) + 
    (temp[3] * 256 * 3);

free(msg);/*Free msg since it is no longer needed*/

/*Open pathname*/
umask(0);
int fd = open(pathname, flags, mode);

free(pathname);/*Free pathname since it is no longer needed*/

/*Prepare response*/
char * response = malloc(sizeof(int) * 2);
if(response == NULL) {
    perror("Allocation error");
    exit(1);
}/*End if*/
response = memset(response, 0, sizeof(int) * 2);

/*Build return message*/
memcpy(&response[0], &fd, sizeof(fd));
memcpy(&response[4], &errno, sizeof(fd));

/*Can't guarante socket will accept all we try to write, cope*/
int num, put;
int left = sizeof(int) * 2; put = 0;
while(left > 0) {
    if((num = write(connfd, response + put, left)) < 0) {
        perror("inet_wstream: write");
        exit(1);
    } else {
        left -= num;
        put += num;
    }/*End else*/
}/*End while*/

free(response);/*Free response since it is no longer needed*/

return;
}/*End Open*/
Apoplexy answered 23/4, 2013 at 20:46 Comment(0)
C
58

Add #include <unistd.h> include directive in your program.

read and write functions are declared in unistd.h and you need a declaration of your functions before to be able to call them.

Cytotaxonomy answered 23/4, 2013 at 20:48 Comment(5)
Whoops, I somehow missed that directive. I didn't think it would even compile/run correctly if it was missing a directive, so it never even crossed my mind to check. Thanks.Apoplexy
@Apoplexy C89 has an implicit declaration rule, if there is no function declaration for a function identifier used in a source file, C assumes it's a function that returns int and takes an unspecified number of arguments. C99 and C11 no longer have this implicit declaration rule.Cytotaxonomy
@ouah: C99 and C11 forbid function calls without a visible declaration, but a violation of that rule merely requires the compiler to issue a diagnostic message. A warning qualifies. gcc, in particular, prints mere warnings for a lot of things that the standard says are constraint violations. It's legal, but IMHO unfortunate (I'd prefer gcc to be stricter by default). You can make it stricter by giving the -pedantic-errors option and specifying a standard (-std=c90/-ansi, -std=c99, -std=c1x/std=c11`).Morell
@KeithThompson My point was that this implicit declaration rule was removed. A compiler is allowed to stop translation and a C program that assumes implicit declaration is not a strictly conforming program.Cytotaxonomy
@ouah: Right, I was expanding on what you said, not disagreeing.Morell
I
3

Implicit function declarations are those that the compiler sees the first time used as a function call (as opposed to those where a prototype or function definition is seen first).

"System calls" are no exception to this rule, since the C Standard(s) don't make a distinction between "ordinary functions" and "system calls". You likely forgot to include the relevant header providing the prototype (unistd.h).

Ious answered 23/4, 2013 at 20:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.