C: Implizite Deklaration der Funktion

Lesezeit: 4 Minuten

Ich arbeite an einer Aufgabe, bei der wir unseren eigenen RPC-Client entwickeln. Beim Kompilieren meines Serverteils erhalte ich Warnungen für Folgendes:

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

Ich verstehe, dass ich normalerweise diese Warnung erhalten würde, wenn ich eine Funktion nach meinem Haupt erstellen würde, z.

int main() {
    doSomething();
}

void doSomething() {
    ...
}

Im obigen Fall sollte es sich über die von mir erstellte Funktion “doSomething” beschweren.

Warum sollte sich mein Compiler dann darüber beschweren, dass ein Systemaufruf implizit deklariert wurde, wenn er in einer Funktion erscheint, die vor dem main deklariert wurde? Unten ist die Funktion, in der der Systemaufruf erscheint.

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*/

Hinzufügen #include <unistd.h> Direktive in Ihr Programm aufnehmen.

read und write Funktionen sind in deklariert unistd.h und Sie brauchen vorher eine Deklaration Ihrer Funktionen, um sie aufrufen zu können.

  • Hoppla, ich habe diese Anweisung irgendwie verpasst. Ich hätte nicht gedacht, dass es richtig kompiliert / ausgeführt wird, wenn eine Direktive fehlt, also kam es mir nie in den Sinn, dies zu überprüfen. Vielen Dank.

    – kubiej21

    23. April 2013 um 20:53 Uhr

  • @kubiej21 C89 hat eine implizite Deklarationsregel, wenn es keine Funktionsdeklaration für einen in einer Quelldatei verwendeten Funktionsbezeichner gibt, C nimmt an, dass es sich um eine Funktion handelt, die zurückkehrt int und akzeptiert eine unbestimmte Anzahl von Argumenten. C99 und C11 haben diese implizite Deklarationsregel nicht mehr.

    – au

    23. April 2013 um 20:56 Uhr

  • @ouah: C99 und C11 verbieten Funktionsaufrufe ohne sichtbare Deklaration, aber ein Verstoß gegen diese Regel erfordert lediglich, dass der Compiler eine Diagnosemeldung ausgibt. Eine Verwarnung gilt. Insbesondere gcc gibt für viele Dinge, die der Standard vorschreibt, nur Warnungen aus Beschränkungsverletzungen. Es ist legal, aber meiner Meinung nach unglücklich (ich würde es vorziehen, wenn gcc standardmäßig strenger wäre). Sie können es strenger machen, indem Sie die angeben -pedantic-errors Option und Angabe eines Standards (-std=c90/-ansi, -std=c99, -std=c1x/std=c11`).

    – Keith Thompson

    23. April 2013 um 21:11 Uhr

  • @KeithThompson Mein Punkt war, dass diese implizite Deklarationsregel entfernt wurde. Ein Compiler darf die Übersetzung stoppen, und ein C-Programm, das von einer impliziten Deklaration ausgeht, ist kein strikt konformes Programm.

    – au

    23. April 2013 um 21:22 Uhr

  • @ouah: Richtig, ich habe das, was du gesagt hast, erweitert, nicht widersprochen.

    – Keith Thompson

    23. April 2013 um 21:49 Uhr

Implizite Funktionsdeklarationen sind diejenigen, die der Compiler zum ersten Mal als Funktionsaufruf verwendet sieht (im Gegensatz zu denen, bei denen zuerst ein Prototyp oder eine Funktionsdefinition gesehen wird).

„Systemaufrufe“ sind keine Ausnahme von dieser Regel, da die C-Standards keinen Unterschied zwischen „gewöhnlichen Funktionen“ und „Systemaufrufen“ machen. Sie haben wahrscheinlich vergessen, den relevanten Header einzufügen, der den Prototyp bereitstellt (unistd.h).

1225220cookie-checkC: Implizite Deklaration der Funktion

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy