Forum: Compiler & IDEs [gcc,clang] kein Error bei Funktionsaufruf mit falschen Parametern


von Mampf F. (mampf) Benutzerseite


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

: Verschoben durch Moderator
von thomil (Gast)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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. ;-)

von Oliver S. (oliverso)


Lesenswert?

uint32_t get_config(void);

error: too many arguments to function 'get_config'
   10 |     get_config(a, b, c);

Wenn dir das zu aufwendig ist, hilft auch -Wmissing-prototypes

Oliver

: Bearbeitet durch User
von Mampf F. (mampf) Benutzerseite


Lesenswert?

OMFG ... das ist mir in meinen bestimmt (gefühlten) zigtausend Stunden 
C-Programmierung nie über den Weg gelaufen!

Dann wird auch gemeckert, vielen Dank!

von vielleicht schon umgesetzt? (Gast)


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?

von vielleicht schon umgesetzt? (Gast)


Lesenswert?

Mampf F. schrieb:
> Dem Compiler ist das egal ...

Also ich bekomme die Warnung "too many arguments".

Vielleicht wirlich mit -std=c2x probieren ;-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ich habe den Thread mal verschoben, denn "Projekte & Code" sind nicht 
für Fragen vorgesehen, sondern zur Vorstellung fertiger Projekte.

Der Untertitel lautet:

Hier könnt ihr eure Projekte, Schaltungen oder Codeschnipsel vorstellen 
und diskutieren. Bitte hier keine Fragen posten!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Ich habe den Thread mal verschoben

Danke, war mir gar nicht aufgefallen.

von vielleicht schon umgesetzt? (Gast)


Lesenswert?

Jörg W. schrieb:
> Auf Seite 107

Das ist aber das gleiche wie bei C99.  Wo ist dann der Unterschied? Dann 
muss man ja es nicht extra erwähnen (weil sich nichts ändert).

Ich glaube aber irgendwo gelesen zu haben (Blogs?), dass da was kommen 
wird.

von vielleicht schon umgesetzt? (Gast)


Lesenswert?


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
von Mampf F. (mampf) Benutzerseite


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!

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Mampf F. schrieb:
> Wieso missing-prototypes nicht bei all, pedantic oder extra dabei ist,
> ist mir allerdings ein Rätsel!

Weil seit 1989 sowieso jeder C-Programmierer automatisch Prototypen 
schreibt? ;-)

Nein, weiß es auch nicht. Diese verschiedenen Warn-Optionen haben sich 
halt auch weiterentwickelt mit der Zeit.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Nachdenklicher (Gast)


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.

von Mampf F. (mampf) Benutzerseite


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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Markus F. (mfro)


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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Rolf M. (rmagnus)


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.

von Markus F. (mfro)


Lesenswert?

... und davon, ob man's richtig oder falsch macht ;)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.