[gcc,clang] kein Error bei Funktionsaufruf mit falschen Parametern

Persönliche Seite #6758469
Lesenswert?

Guten Mittag,

in einem Projekt habe ich mehrere .c Files.
1
api.h:
2
uint32_t get_config();
3

4
api.c:
5
uint32_t get_config()
6
{
7
    ...
8
}

und ein weitere c-File, das falsch die Funktion aufruft:
1
io.c:
2
#include "api.h"
3
get_config(a, b, c);

Dem Compiler ist das egal ... Die Variablen werden in get_config auch 
nicht verwendet, aber es wäre schön, wenn es dennoch einen Fehler geben 
würde.

Ich hab bereits das hier in jedem c-File aktiviert:
1
#pragma GCC diagnostic error "-Wpedantic"
2
#pragma GCC diagnostic error "-Wall"
3
#pragma GCC diagnostic error "-Wextra"

Aber der Compiler sagt mir nicht, dass Prototypen-Definition und 
eigentlicher Funktionsaufruf nicht zusammen passt.

Habt ihr eine Idee, wie ich das erzwingen kann?

Viele Grüße,
Mampf
Gast #6758484
Lesenswert?

In C bedeutet eine Deklaration ohne Parameter, dass die Funktion 
beliebig viele int Parameter übernehmen kann. Wenn die Funktion 
tatsächlich keine Parameter übernehmen soll, muss sie folgendermaßen 
deklariert werden:
1
uint32_t get_config(void);

In diesem Fall sollten die Compiler dann auch einen Fehler werfen.
Moderator Persönliche Seite #6758487
Lesenswert?

thomil schrieb:
> In C bedeutet eine Deklaration ohne Parameter, dass die Funktion
> beliebig viele int Parameter übernehmen kann.

Nicht einmal das.

Es bedeutet, dass sie eine beliebige Zahl von Parametern nicht näher 
spezifizierten Typs übernehmen kann. Die Implementierung der Funktion 
muss dann natürlich die exakt gleiche Zahl mit den passenden Typen 
beschreiben.

Die Implementierung einer solchen Funktion sähe dann so aus:
1
void get_config(a, b, c)
2
        int a;
3
        double b, c;
4
{
5
   // tu was mit a, b und c
6
}

Solchen Code schreibt man aber schon seit 30 Jahren nicht mehr. ;-)
Gast #6758584
Lesenswert?

Ist es nicht so, dass man im neuen c2x-Standard auf void verzichten 
kann? Irgendwo habe ich sowas schon gelesen.

Vielleicht wird diese Option schon von irgendeinem Compiler unterstützt?
Moderator Persönliche Seite #6758609
Lesenswert?

vielleicht schon umgesetzt? schrieb:
> Ist es nicht so, dass man im neuen c2x-Standard auf void verzichten
> kann?

Jein.

Die alte (prä-C89) Form ist im letzten Standard explizit als 
"deprecated" markiert worden, aber noch zulässig.

Den derzeit letzten Entwurf dessen, was mal C23 werden soll (und derzeit 
noch stark im Fluss ist), kannst du hier einsehen:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf

(Btw., die Leute machen dort einen großartigen Job, derartige 
Veröffentlichungen gegen Anfeindungen von Seiten der Standard-Gremiem zu 
verteidigen.)

Auf Seite 107 findest du:
1
For a function declarator without a parameter type list: if it is part
2
of a definition of that function the function has no parameters and the
3
effect is as if it were declared with a parameter type list consisting of
4
the keyword void; otherwise it specifies that no information about the
5
number or types of the parameters is supplied.

D.h. also, nur wenn die Funktionsdeklaration zugleich eine Definition 
ist, dokumentiert die leere Klammer, dass die Funktion keine Parameter 
übernimmt.

In einer separten (extern-)Deklaration dagegen dokumentiert sie das 
historische Verhalten, dass über die Parameter nichts Genaues bekannt 
ist.

Bei C++ ist das anders, die mussten halt den historischen Ballast nicht 
unterstützen, den das prä-C89 der Sprache C mit auf den Weg gegeben hat.
Moderator Persönliche Seite #6758710
Lesenswert?

vielleicht schon umgesetzt? schrieb:
> Ich glaube aber irgendwo gelesen zu haben (Blogs?), dass da was kommen
> wird.

Du kannst ja glauben, was du willst (wenngleich es ein paar 
Institutionen gibt, die sich auf sowas spezialisiert haben ;-).

Was ich dir gezeigt habe ist, was nach derzeitigem Erkenntnisstand im 
nächsten Standard dazu stehen wird. Die Zeit, da noch Änderungen 
einzutüten, dürfte übrigens allmählich abgelaufen sein: WG14 hat mit den 
bereits eingereichten Papers, die Änderungen in Richtung C23 beantragen, 
bereits alle Hände voll zu tun, diese noch fristgerecht abzuarbeiten.

Insofern würde ich jetzt ganz stark davon ausgehen, dass diese Passage 
in der von mir zitierten Form sich auch in C23 wiederfinden wird.
Persönliche Seite #6759026
Lesenswert?

Ich hab meinen Pragmas noch das "missing Prototypes" hinzugefügt:
1
#pragma GCC diagnostic error "-Wpedantic"
2
#pragma GCC diagnostic error "-Wall"
3
#pragma GCC diagnostic error "-Wextra"
4
#pragma GCC diagnostic error "-Wmissing-prototypes"

dann hatte er zuerst gemotzt, dass get_config(); kein Prototype ist und 
nachdem ich das auf get_config(void); änderte, motzte er, dass der 
Funktionsaufruf nicht zum Prototyp passt.

Passt also - perfekt, Vielen Dank!

PS: Wieso missing-prototypes nicht bei all, pedantic oder extra dabei 
ist, ist mir allerdings ein Rätsel!
Gast #6759093
Lesenswert?

Jörg W. schrieb:
> Weil seit 1989 sowieso jeder C-Programmierer automatisch Prototypen
> schreibt? ;-)

Leider nein. Ich habe bei einem Projekt bei der Arbeit eine Bibliothek 
aus einem anderen Projekt (vor ca 20 Jahren begonnen) übernommen. Mein 
überbeordnetes Projekt hat allerdings das Äquivalent zu 
"-Wmissing_prototypes" (wir arbeiten hier leider nicht mit GCC) gesetzt, 
was das Projekt, aus dem die Biblothek kam, nicht hatte. (Ja, so hab ich 
auch geguckt)

Resultat: Ich habe erst mal einen Tag lang Prototypen nachgepflegt und 
in den Funktionsaufrufen entsprechende explizite Casts, um das Ding ohne 
Fehler und Warnungen zu kompilieren. Wäre derjenige, der das Ding damals 
verbrochen hat, noch im Unternehmen, hätte ich ihm vermutlich eine 
ausgedruckte Liste der Compilerwarnungen um die Ohren gehauen.
Persönliche Seite #6759339
Lesenswert?

Rolf M. schrieb:
> Mampf F. schrieb:
>> Ich hab bereits das hier in jedem c-File aktiviert:
>> #pragma GCC diagnostic error "-Wpedantic"
>> #pragma GCC diagnostic error "-Wall"
>> #pragma GCC diagnostic error "-Wextra"
>
> Einfacher (und üblicher) wäre es, das über das Makefile zu machen.

Ja, wenn mein guter Code nicht in miesen Code eingebettet wäre, den man 
mit den Compiler-Flags nicht kompilieren kann.

Da das aber ein SDK eines Anbieters ist, ist er unveränderlich.
#6759506
Lesenswert?

Rolf M. schrieb:
> Mampf F. schrieb:
>>> Einfacher (und üblicher) wäre es, das über das Makefile zu machen.
>>
>> Ja, wenn mein guter Code nicht in miesen Code eingebettet wäre, den man
>> mit den Compiler-Flags nicht kompilieren kann.
>> Da das aber ein SDK eines Anbieters ist, ist er unveränderlich.
>
> Ah, verstehe. Das Problem kann ich nachvollziehen.

Ich nicht so ganz.

Ich kann doch immer $(GOOD_CODE) mit $(GOOD_CODE_FLAGS) und $(BAD_CODE) 
mit $(BAD_CODE_FLAGS) compilieren?
#6759832
Lesenswert?

Jörg W. schrieb:
> Markus F. schrieb:
>> Ich kann doch immer $(GOOD_CODE) mit $(GOOD_CODE_FLAGS) und $(BAD_CODE)
>> mit $(BAD_CODE_FLAGS) compilieren?
>
> Hängt davon ab, ob deine Buildumgebung diese beiden Kategorien irgendwie
> trennen kann.

Und davon, ob $(GOOD_CODE) und $(BAD_CODE) überhaupt getrennt übersetzt 
oder über irgendwelche Includes vor dem eigentlich Compilevorgang erst 
noch miteinander verheiratet werden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren