Warnung: Ignorieren des Rückgabewerts von ‘scanf’, deklariert mit dem Attribut warn_unused_result

Lesezeit: 9 Minuten

Benutzeravatar von vipin
Vipin

#include <stdio.h>

int main() {
    int t;
    scanf("%d", &t);
    printf("%d", t);
    return 0;
}

Ich habe den obigen C-Code mit ideone.com kompiliert und die folgende Warnung wurde angezeigt:

prog.c: In Funktion ‘main’:
prog.c:5: Warnung: Rückgabewert von ‘scanf’ wird ignoriert, deklariert mit Attribut warn_unused_result

Kann mir jemand helfen, diese Warnung zu verstehen?

Benutzeravatar von Evan Teran
Evan Teran

Die Schreiber Ihrer libc haben entschieden, dass der Rückgabewert von scanf sollte in den meisten Fällen nicht ignoriert werden, also haben sie ihm ein Attribut gegeben, das den Compiler anweist, Ihnen eine Warnung zu geben.

Wenn der Rückgabewert wirklich nicht benötigt wird, ist alles in Ordnung. Es ist jedoch normalerweise am besten, es zu überprüfen, um sicherzustellen, dass Sie tatsächlich erfolgreich gelesen haben, was Sie zu tun glauben.

In Ihrem Fall könnte der Code so geschrieben werden, um die Warnung (und einige Eingabefehler) zu vermeiden:

#include <stdio.h>

int main() {
    int t;
    if (scanf("%d", &t) == 1) {
        printf("%d", t);
    } else {
        printf("Failed to read integer.\n");
    }
    return 0;
}

  • Was ich seltsam fand: Es scheint, dass der Compiler eine Warnung über unbenutzte Ergebnisse ausgibt, sich aber nur über scanf beschwert. Vielleicht wissen es viele nicht, aber printf gibt auch einen Wert zurück, und es scheint, dass er sich nicht über dieses verworfene Ergebnis dort beschwert.

    – flolo

    1. September 2011 um 14:44 Uhr


  • Der Compiler gibt diese Warnung nur für Funktionen aus, die dieses bestimmte Attribut haben. Wenn printf scheitert, da kann man nicht viel machen. Aber scanf kann ziemlich leicht scheitern. Alles, was ich tun muss, ist tippen 'A' anstelle einer Ganzzahl und Ihr Programm ist kaputt.

    – Evan Teran

    1. September 2011 um 14:50 Uhr

  • Danke für die Antworten Jungs. Dieses Problem ist erst heute aufgetreten. Ich habe den gleichen Compiler schon so oft verwendet, aber plötzlich kam diese Warnung.

    – Vipin

    1. September 2011 um 15:00 Uhr


  • @Evan Teran: Ah Thx, ich kenne den Compiler nicht und dachte, es wäre ein “globales” Flag/Schalter/Attribut. Aber wenn es ein Funktionsattribut ist und nur einige sie haben, dann verstehe ich das.

    – flolo

    1. September 2011 um 15:03 Uhr

  • Hier ist die Dokumentation auf GCCs warn_unused_result Funktionsattribut. Wenn Sie GCC (das von Ideone verwendet wird) verwenden und in Ihrem nachsehen stdio.h Header-Datei, das werden Sie sehen scanf und seine Verwandten sind mit gekennzeichnet warn_unused_result Attribut, aber printf und seine Verwandten nicht.

    – Adam Rosenfield

    1. September 2011 um 15:29 Uhr

Benutzeravatar von Alexandre C
Alexandre C.

Die Warnung weist (zu Recht) darauf hin, dass es keine gute Idee ist, den Rückgabewert von nicht zu überprüfen scanf. Die Funktion scanf explizit deklariert wurde (über a gcc-Funktionsattribut), um diese Warnung auszulösen, wenn Sie ihren Rückgabewert verwerfen.

Wenn Sie diesen Rückgabewert wirklich vergessen möchten, während Sie den Compiler (und Ihr Gewissen) glücklich machen, können Sie den Rückgabewert auf void umwandeln:

(void)scanf("%d",&t);

  • GCC warnt auch dann, wenn Sie dies tun. Weitere Informationen finden Sie in dieser Diskussion gcc.gnu.org/bugzilla/show_bug.cgi?id=25509

    – Kraffetti

    6. Dezember 2013 um 15:52 Uhr

  • Wenn Sie eine Dummy-Variable zuweisen, erhalten Sie möglicherweise eine weitere Warnung, dass die Variable zugewiesen, aber nie verwendet wird.

    – Craig McQueen

    19. Juni 2015 um 6:09 Uhr


  • WARNUNG: Viele Compiler werden diese void-Umwandlung wegoptimieren, da sie unnötig ist, und dann wird immer noch ein unbenutzter Variablenfehler erzeugt.

    – WohlhabendeEule

    15. Juli 2015 um 20:25 Uhr

  • @AffluentOwl Die void cast ist die Standardkonvention zu sagen „dieses Ergebnis wird absichtlich nicht verwendet“ und allgemein anerkannt – außer von gcc, weil jemand (Stallmann?) vor 20 Jahren entschieden hat, dass es keine Möglichkeit geben sollte, a zu ignorieren warn_unused_result.

    – fuz

    15. Januar 2016 um 15:12 Uhr

  • (void)! ... kann verwendet werden, um das zumindest zu vermeiden gcc Warnung (@kraffenetti @AffluentOwl), siehe gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34 .

    – Rivalität

    28. Januar 2019 um 19:54 Uhr


Benutzeravatar von Quigi
Quigi

Ich habe Ihr Beispiel mit gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3 ausprobiert. Die Warnung wird nur dann ausgegeben, wenn optimiert wird, zB mit Option -O2 oder -O3. Das Anfordern aller Warnungen (-Wall) spielt keine Rolle. Die klassische Redewendung des Casting to Void hat keine Wirkungwird die Warnung nicht unterdrückt.

Ich kann die Warnung schriftlich zum Schweigen bringen

if(scanf("%d",&t)){};

das funktioniert, aber es ist ein bisschen obskur für meinen Geschmack. Leeres {} vermeidet eine weitere Warnung -Wempty-body

  • dies kann eine zusätzliche Leerkörperwarnung des Compilers verursachen

    – Kraffetti

    6. Dezember 2013 um 15:50 Uhr


  • Wenn ich diese Art von Code sehe, mit einem Semikolon am Ende von an if, ich denke, es kann ein Fehler sein. Es erfordert mindestens einen erläuternden Kommentar.

    – Craig McQueen

    19. Juni 2015 um 6:11 Uhr


  • So viele Upvotes für solch einen unverantwortlichen Cowboy-Ratschlag?? schaudern

    – Mawg sagt, Monica wieder einzusetzen

    13. Juli 2016 um 17:23 Uhr


  • Mawg hat Recht, Sie sollten immer den Rückgabewert von scanf überprüfen. Ich suchte nach einer Möglichkeit, es zum Schweigen zu bringen, eher als Sport, nicht als Ratschlag für gutes Programmieren. Ich finde es immer noch seltsam, dass (a) die Optimierung beeinflusst, ob Sie die Warnung erhalten, und (b) -Wall nicht.

    – Quigi

    4. April 2017 um 14:58 Uhr

Mach das:

int main() {
    int t;
    int unused __attribute__((unused));
    unused = scanf("%d",&t);
    printf("%d",t);
    return 0;
}

Benutzeravatar von DrBeco
DrBeco

Nachdem ich alle Antworten und Kommentare auf dieser Seite gelesen habe, sehe ich diese weiteren Optionen nicht, um die Warnung zu vermeiden:

Wann kompilieren mit gcc Sie können Ihrer Befehlszeile Folgendes hinzufügen:

gcc -Wall -Wextra -Wno-unused-result proc.c -o prog.x

Andere Option ist zu verwenden -O0 als “Optimierungsstufe Null” ignoriert die Warnung.

Cast to verwenden (void) ist einfach nicht zu gebrauchen beim Kompilieren mit gcc

Wenn Sie Ihren Code debuggen, können Sie immer verwenden assert() wie im folgenden Beispiel:

u = scanf("%d", &t);
assert(u == 1);

Aber jetzt, wenn Sie “asserting via” deaktivieren #define NDEBUG du bekommst ein -Wunused-but-set-variable. Diese können Sie dann ausschalten zweite Warnung auf eine von zwei Arten:

  1. Hinzufügen -Wno-unused-but-set-variable zu deinem gcc Kommandozeile bzw
  2. Variable mit Attribut deklarieren: int u __attribute__((unused));

Wie in einer anderen Antwort erwähnt, ist die zweite Option leider nicht sehr portabel, obwohl sie die beste Option zu sein scheint.

Endlich das Definierte MAKRO Unten kann Ihnen helfen, wenn Sie sind sicher Sie möchten die Rückgabe einer bestimmten Funktion ignorieren, möchten aber die Warnungen nicht ausschalten alle unbenutzte Rückgaben von Funktionen:

#define igr(x) {__typeof__(x) __attribute__((unused)) d=(x);} 

double __attribute__ ((warn_unused_result)) fa(void) {return 2.2;}
igr(fa());

Siehe auch diese Antwort

  • Das assert ist ein Missbrauch. Wenn ein assert fehlschlägt, hat der Programmierer fehlerhaften Code geschrieben. Wenn ich eintrete A in Ihr Programm, Ihr Code bricht ab, daher hat er einen Fehler.

    – Antti Haapala – Слава Україні

    7. September 2018 um 16:56 Uhr

  • Danke für deinen Kommentar. Ich stimme dem zu, wenn Sie verwenden assert da missverstehst du aus meiner antwort ja einen abuse. Die obige Antwort listet verschiedene Optionen auf, um mit “unbenutzter Rückgabe von scanf” umzugehen, das ist der Hauptpunkt. Das assert Teil Staaten wenn Debuggen. Ich denke, es ist gut, alle Optionen als lehrreiche, informative Antwort “aufzuschreiben”, damit die Leute alle Werkzeuge lernen und fundierte Entscheidungen treffen können. Auch deshalb finde ich deinen Kommentar hilfreich, damit die Leute das nicht auch noch falsch lesen und das missbrauchen assert() einen Job zu machen, der nicht dafür ist. Vielen Dank.

    – DrBeco

    7. September 2018 um 17:36 Uhr

Eine Möglichkeit, dies zu lösen, ist die IGUR() Funktion wie unten zu sehen. Extrem hässlich, aber dennoch einigermaßen tragbar. (Für alte Compiler, die nicht verstehen inline nur #define inline /*nothing*/wie gewöhnlich.)

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

inline void IGUR() {}  /* Ignore GCC Unused Result */
void IGUR();  /* see https://stackoverflow.com/a/16245669/490291 */

int
main(int argc, char **argv)
{
  char  buf[10*BUFSIZ];
  int   got, fl, have;

  fl    = fcntl(0, F_GETFL);
  fcntl(0, F_SETFL, fl|O_NONBLOCK);
  have = 0;
  while ((got=read(0, buf, sizeof buf))>0)
    {
      IGUR(write(1, buf, got));
      have = 1;
    }
  fcntl(0, F_SETFL, fl);
  return have;
}

BTW dieses Beispiel, nonblocking, kopiert von stdin zu stdout bis alle wartenden Eingaben gelesen wurden, Rückkehr true (0) wenn nichts da war, sonst false (1). (Es verhindert die 1s-Verzögerung in etwas wie while read -t1 away; do :; done in bash.)

Kompiliert ohne Warnung unter -Wall (Debian Jessie).

Bearbeiten: IGUR() muss ohne definiert werden inline, so dass es für den Linker verfügbar wird. Sonst mit cc -O0 es könnte fehlschlagen. Siehe: https://stackoverflow.com/a/16245669/490291

Edit2: Neuer gcc benötigen inline vorher sein void.

  • Das assert ist ein Missbrauch. Wenn ein assert fehlschlägt, hat der Programmierer fehlerhaften Code geschrieben. Wenn ich eintrete A in Ihr Programm, Ihr Code bricht ab, daher hat er einen Fehler.

    – Antti Haapala – Слава Україні

    7. September 2018 um 16:56 Uhr

  • Danke für deinen Kommentar. Ich stimme dem zu, wenn Sie verwenden assert da missverstehst du aus meiner antwort ja einen abuse. Die obige Antwort listet verschiedene Optionen auf, um mit “unbenutzter Rückgabe von scanf” umzugehen, das ist der Hauptpunkt. Das assert Teil Staaten wenn Debuggen. Ich denke, es ist gut, alle Optionen als lehrreiche, informative Antwort “aufzuschreiben”, damit die Leute alle Werkzeuge lernen und fundierte Entscheidungen treffen können. Auch deshalb finde ich deinen Kommentar hilfreich, damit die Leute das nicht auch noch falsch lesen und das missbrauchen assert() einen Job zu machen, der nicht dafür ist. Vielen Dank.

    – DrBeco

    7. September 2018 um 17:36 Uhr

Eigentlich hängt es davon ab, was Sie brauchen, wenn Sie nur die Warnung des Compilers deaktivieren möchten, können Sie den Rückgabewert der Funktion einfach ignorieren, indem Sie die Konvertierung erzwingen, oder Sie können einfach damit umgehen, die Bedeutung der scanf Funktion ist die Anzahl der Benutzereingaben.

==== aktualisieren ====

Sie können verwenden

(void) scanf("%d",&t);

den Rückgabewert von zu ignorieren scanf

  • Minus eins für das Befürworten des Ignorierens von Warnungen. Klügere Leute als du und ich sind für sie verantwortlich. Sie sagen dir hilfreiche Dinge. Ihre Beachtung führt zu einer besseren Codequalität. Ignorieren Sie sie auf eigene Gefahr und setzen Sie sich bitte nicht dafür ein, dass andere sie ignorieren oder unterdrücken

    – Mawg sagt, Monica wieder einzusetzen

    9. August 2016 um 16:18 Uhr

  • was auch immer, ich weiß, wo die Warnung ist, und ich weiß, dass sie meinem Programm schaden wird. Und einige Projekte behandeln Warnungen möglicherweise als Fehler. Ich meine, die Warnung loszuwerden

    – Acton

    11. August 2016 um 8:28 Uhr

  • Beseitigen Sie Warnungen, indem Sie den Fehler behandeln, nicht indem Sie ihnen ausweichen …

    – Woodrow Douglass

    17. Oktober 2016 um 18:03 Uhr

  • Dies funktioniert nicht (mehr) für gcc 5.4.x. Ich bekomme immer noch die gleiche Warnung, wenn ich einen (void) Cast vor die Funktion setze.

    – Carlo Holz

    15. Dezember 2016 um 16:44 Uhr

  • @WoodrowDouglass Warnungen sind keine Fehler. Wenn Sie eine Warnung sehen, untersuchen Sie die Leitung und stellen fest, ob sie so in Ordnung ist, wie sie ist. In einigen Fällen möchten Sie die Rückgabe von scanf wirklich ignorieren, also ist es, um es ganz klar auszudrücken, dumm, keine Möglichkeit zu haben, die Warnung für diese eine Zeile zu entfernen. Sie möchten nicht, dass bereits geprüfter und als sicherer Code Warnungen ausgibt, da Sie dann das Rausch-/Signalverhältnis in der Compilerausgabe erhöhen.

    – Lelanthran

    7. April 2018 um 18:49 Uhr


1413000cookie-checkWarnung: Ignorieren des Rückgabewerts von ‘scanf’, deklariert mit dem Attribut warn_unused_result

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

Privacy policy