Guten Mittag,
in einem Projekt habe ich mehrere .c Files.
1
api.h:
2
uint32_tget_config();
3
4
api.c:
5
uint32_tget_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
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_tget_config(void);
In diesem Fall sollten die Compiler dann auch einen Fehler werfen.
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
voidget_config(a,b,c)
2
inta;
3
doubleb,c;
4
{
5
// tu was mit a, b und c
6
}
Solchen Code schreibt man aber schon seit 30 Jahren nicht mehr. ;-)
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
OMFG ... das ist mir in meinen bestimmt (gefühlten) zigtausend Stunden
C-Programmierung nie über den Weg gelaufen!
Dann wird auch gemeckert, vielen Dank!
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?
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!
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.
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.
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.
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!
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.
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.
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.
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.
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.
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?
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.
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.