2017-03-29 3 views
0

Wie kann ich gcc anweisen, mich vor ungültigen Funktionszeiger-Konvertierungen zu warnen, wie es g ++ für den folgenden Code tun würde?Wie man gcc anweist, mich über ungültige Funktionszeigerkonvertierung zu warnen, gerade wie g ++ tun würde?

Und .. warum warnt mich gcc nicht davor? Was könnte/wird passieren, wenn ein Zeiger auf ein to do_something() übergeben wird?

#include <stdio.h> 

typedef void (*void_func_t)(); 
typedef void (*void_int_func_t) (int, int, int); 

void do_something(void_func_t f) 
{ 
    void_int_func_t foo = f; 
    foo(1,2,3); 
} 

void a() 
{ 
    printf("a\n"); 
} 

void b(int one, int two, int three) 
{ 
    printf("%i, %i, %i\n", one, two, three); 
} 

int main() 
{ 
    do_something(a); 
    do_something(b); 
    return 0; 
} 

output:

➜ gcc -W -Wall -Werror func.c 
➜ ./a.out 
a 
1, 2, 3 

C++, würde jedoch warnen/geben Fehler

g++ -W -Wall -Werror func.c 
func.c: In function ‘void do_something(void_func_t)’: 
func.c:8:27: error: invalid conversion from ‘void_func_t {aka void (*)()}’ to ‘void_int_func_t {aka void (*)(int, int, int)}’ [-fpermissive] 
func.c: In function ‘int main()’: 
func.c:25:19: error: invalid conversion from ‘void (*)(int, int, int)’ to ‘void_func_t {aka void (*)()}’ [-fpermissive] 
func.c:6:6: error: initializing argument 1 of ‘void do_something(void_func_t)’ [-fpermissive] 
+0

Können Sie 'clang' anstelle von' gcc' verwenden, wo '-Weverything' verfügbar ist? –

+1

C und C++ sind verschiedene Sprachen. Wenn Sie eine Obsoletzenz, aber eine gültige C-Funktion verwenden, warum sollte ein kompatibler Compiler warnen? – Olaf

+0

nein, @FiddlingBits das ist in meinem Fall nicht möglich. @Olaf, mir war nicht klar, dass es einen so großen Unterschied zwischen dem Löschen einer Funktion wie "void foo()" oder "void foo (void)" in C gibt. Darum habe ich mich gewundert und warum Ich habe diese Frage gestellt. – yussuf

Antwort

5

Ein Funktionsprototyp mit leeren Klammern ist ein obsolescent Funktion. Benutze es nicht.

Wenn Sie die richtige Erklärung verwenden, werden Sie Warnungen erhalten:

typedef void(*void_func_t)(void); 

Aufgrund dieser alten Funktion, die Typen void(*)() und void(*)(int, int, int) kompatibel sind. Der erstgenannte Typ benötigt eine nicht spezifizierte Anzahl von Argumenten. Dies ist doppelt problematisch, da der Compiler keine Warnung enthält und wenn Sie die Funktion mit der falschen Anzahl von Argumenten aufrufen, ist das Verhalten nicht definiert.

Im Gegensatz zu C bedeuten in C++ leere Klammern, dass die Funktion keine Argumente annimmt, daher entspricht void(*)()void(*)(void).


(Zitiert nach: ISO/IEC 9899: 201x 6.11.6 Funktionsdeklaratoren 1)
Die Verwendung von Funktion mit leeren Klammern Deklaratoren (nicht Parameter Typ Deklaratoren Prototyp-Format) ist ein veraltete Funktion.

+0

danke für die Referenz, es hilft natürlich zu wissen, was zu suchen ... scheint wie -Werstrict-Prototypen würde helfen, diese Gerüche zu erkennen, aber ich befürchte, dass würde zu 1000 Warnungen in meinem Code-Basis führen ... – yussuf

Verwandte Themen