Warnungen mit -Wextra und -pedantic
-
Um ANSI-C-kompatibel (möglichst plattformunabhängig) zu arbeiten, fehlt noch -ansi:
-ansi: Abschalten von Eigenschaften des gcc, die nicht mit ISO C90 kompatibel sind, -pedantic: Warnungen beim Verstoß gegen Vorgaben von ISO C90, -Wall: Warnungen bei fragwürdigen Code-Konstrukten, -Wextra: Warnungen bei weiteren fragwürdigen Code-Konstrukten, -Werror: Behandlung von Warnungen als Fehler.
-
@taljeth: Wer ist "man"?
CFLAGS= [b]-std=gnu99[/b] -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude
läuft übrigens problemlos durch.
Bei tyndur finde ich:
CC=i586-elf-gcc -m32 -g -c -fno-stack-protector -nostdinc -fno-leading-underscore -fno-omit-frame-pointer -Wall -Werror -Wstrict-prototypes -fno-strict-aliasing -O2 -fno-builtin -I
-
Plattformunabhängigkeit (damit ist wohl Compilerunabhängigkeit gemeint) ist für ein OS nicht erstrebenswert.
Durch die Verwendung von Inline Assembler, Assembler in externen Dateien (Unterstrich vor Symbolen oder nicht), sowie selbstgebauten Linker-Skripten wird die Wartung von verschiedenen Konfigurationen für unterschiedliche Compiler zu einer unnötigen Belastung. Dazu kommt noch die seperate Verwaltung der dann nötigen Makefiles, Projekt-Dateien, etc. (Ein OS ist keine Übung in der Verwaltung von verschiedenen Projektkonfigurationen.)
Eine frühe Festlegung auf einen bestimmten Compiler, Linker, sowie Umgebung, ermöglicht es sich auf die wesentlichen Dinge beim OS-Dev zu konzentrieren. Zum Beispiel GCC >=4.1 und Binutils >=2.19 sind solide, gut getestet, haben guten Support (Updates), und sind auch sehr gut zum selbst Kompilieren in exotischen Konfigurationen geeignet (gerade unter Windows).
Als Standard gnu99 zu wählen ist dann nur konsequent und erlaubt viele nützliche Erweiterungen, die GCC bietet, zu nutzen. Default ist beim GCC gnu89, aber C99/gnu99 bietet halt auch ein paar nette Erweiterungen.
-
Erhard Henkes schrieb:
@taljeth: Wer ist "man"?
Jeder, der mit dem gcc C programmiert.
Ich hoffe, über c99 gegenüber c89 müssen wir nicht großartig reden. Es ist neuer, es ist besser, es ist schöner. Was die Entscheidung zwischen c99 und gnu99 betrifft, kann man sicher streiten, ob man sich an einen bestimmten Compiler binden will. Ich möchte nur darauf hinweisen, dass du an jeder Stelle, an der ein __attribute__ auftaucht oder Inline-Assembler benutzt wird, schon gcc-spezifischen Code hast. Du hast die Entscheidung also wahrscheinlich schon lang getroffen, ohne dir dessen bewusst zu sein.
Bei tyndur finde ich:
CC=i586-elf-gcc -m32 -g -c -fno-stack-protector -nostdinc -fno-leading-underscore -fno-omit-frame-pointer -Wall -Werror -Wstrict-prototypes -fno-strict-aliasing -O2 -fno-builtin -I
Die allein selig machende Kommandozeile gibt es nicht. Gerade bei den Warnungen und schon vorhandenem Code muss man halt schauen, was sich aktivieren lässt ohne dass gar nichts mehr geht.
-
Hier die Meldungen von -ansi:
i586-elf-gcc -ansi -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude -c -o flpydsk.o flpydsk.c
In file included from include/flpydsk.h:4,
from flpydsk.c:1:
include/os.h:4: error: expected identifier or '(' before '/' token
include/os.h:4: error: stray '#' in program
include/os.h:28: error: expected specifier-qualifier-list before '/' token
include/os.h:44: error: expected identifier or '(' before '/' token
include/os.h:68: error: expected identifier or '(' before '/' token
include/os.h:85: error: expected identifier or '(' before '/' token
include/os.h:94: error: expected identifier or '(' before '/' token
include/os.h:102: error: expected identifier or '(' before '/' token
include/os.h:111: error: expected declaration specifiers or '...' before 'size_t'
include/os.h:112: error: expected declaration specifiers or '...' before 'size_t'
include/os.h:113: error: expected declaration specifiers or '...' before 'size_t'
include/os.h:114: error: expected declaration specifiers or '...' before 'size_t'
include/os.h:115: error: expected '=', ',', ';', 'asm' or '__attribute__' before
'k_strlen'
include/os.h:118: error: expected declaration specifiers or '...' before 'size_t'
include/os.h:128: error: expected identifier or '(' before '/' token
include/os.h:146: error: expected identifier or '(' before '/' token
include/os.h:150: error: expected identifier or '(' before '/' token
In file included from flpydsk.c:1:
include/flpydsk.h:6: error: expected identifier or '(' before '/' token
In file included from flpydsk.c:1:
include/flpydsk.h:6:47: error: invalid suffix "MB" on integer constant
flpydsk.c:2: error: expected identifier or '(' before '/' token
flpydsk.c:4: error: stray '#' in program
flpydsk.c:17: error: expected identifier or '(' before '/' token
flpydsk.c:31: error: expected identifier or '(' before '/' token
flpydsk.c:39: error: expected identifier or '(' before '/' token
flpydsk.c:54: error: expected identifier or '(' before '/' token
flpydsk.c:67: error: expected identifier or '(' before '/' token
flpydsk.c:81: error: expected identifier or '(' before '/' token
flpydsk.c:90: error: expected identifier or '(' before '/' token
flpydsk.c:98: error: expected identifier or '(' before '/' token
flpydsk.c:112: error: expected identifier or '(' before '/' token
flpydsk.c:113: error: expected identifier or '(' before '/' token
flpydsk.c:114: error: expected identifier or '(' before '/' token
flpydsk.c:115: error: expected identifier or '(' before '/' token
flpydsk.c:133:69: error: missing terminating " character
flpydsk.c:133: error: missing terminating " character
flpydsk.c:140: error: expected identifier or '(' before '/' token
flpydsk.c:148: error: expected identifier or '(' before '/' token
flpydsk.c:161: error: expected identifier or '(' before '/' token
flpydsk.c:167: error: expected identifier or '(' before '/' token
flpydsk.c:173: error: expected identifier or '(' before '/' token
flpydsk.c:183: error: expected identifier or '(' before '/' token
flpydsk.c:194: error: expected identifier or '(' before '/' token
flpydsk.c:204: error: expected identifier or '(' before '/' token
flpydsk.c:212: error: expected identifier or '(' before '/' token
flpydsk.c:223: error: expected identifier or '(' before '/' token
flpydsk.c:231: error: expected identifier or '(' before '/' token
flpydsk.c:257: error: expected identifier or '(' before '/' token
flpydsk.c:268: error: expected identifier or '(' before '/' token
flpydsk.c:293: error: expected identifier or '(' before '/' token
flpydsk.c:299: error: expected identifier or '(' before '/' token
flpydsk.c:305: error: expected identifier or '(' before '/' token
flpydsk.c:317:55: error: invalid suffix "kb" on integer constant
flpydsk.c:318:77: error: invalid suffix "ms" on integer constant
flpydsk.c:318:92: error: invalid suffix "ms" on integer constant
flpydsk.c:318:110: error: invalid suffix "ms" on integer constant
flpydsk.c:322: error: expected identifier or '(' before '/' token
flpydsk.c:352: error: expected identifier or '(' before '/' token
flpydsk.c:369: error: expected identifier or '(' before '/' token
flpydsk.c:378: error: expected identifier or '(' before '/' token
flpydsk.c:381: error: expected identifier or '(' before '/' token
flpydsk.c:384: error: expected identifier or '(' before '/' token
flpydsk.c:386: error: expected '=', ',', ';', 'asm' or '__attribute__' before ':' token
flpydsk.c:424: error: expected identifier or '(' before '/' token
flpydsk.c:438:25: error: invalid suffix "KB" on integer constant
flpydsk.c:441: error: expected identifier or '(' before '/' token
flpydsk.c: In function 'flpydsk_read_directory':
flpydsk.c:460: error: expected expression before '/' token
flpydsk.c:464: error: expected expression before '/' token
flpydsk.c:467:26: error: invalid suffix "KB" on integer constant
flpydsk.c:468:26: error: invalid suffix "KB" on integer constant
flpydsk.c:469:26: error: invalid suffix "KB" on integer constant
flpydsk.c:472:16: error: invalid suffix "KB" on integer constant
flpydsk.c:483:12: error: invalid suffix "KB" on integer constant
flpydsk.c:490:40: error: invalid suffix "KB" on integer constant
flpydsk.c:494:18: error: invalid suffix "KB" on integer constant
flpydsk.c:495:29: error: invalid suffix "KB" on integer constant
flpydsk.c:496:29: error: invalid suffix "KB" on integer constant
flpydsk.c:497:29: error: invalid suffix "KB" on integer constant
flpydsk.c:498:29: error: invalid suffix "KB" on integer constant
flpydsk.c:499:29: error: invalid suffix "KB" on integer constant
flpydsk.c:500:29: error: invalid suffix "KB" on integer constant
flpydsk.c:502:7: error: invalid suffix "st" on integer constant
flpydsk.c:503:60: error: invalid suffix "KB" on integer constant
mingw32-make: *** [flpydsk.o] Error 1Ich bin bezüglich gcc-Compiler kein Experte, aber mein Vorschlag wäre:
Muss: -Werror -Wall
Ziel1: -Wextra
Ziel2: -ansi
Ziel3: -pedantic-std=gnu99 ist, soweit ich das verstanden habe, bereits erfüllt.
-
So wie das für mich aussieht, sollte man für -ansi erstmal alle "// Kommentare" durch "/* Kommentare */" ersetzen und ein Großteil müsste erledigt sein.
-
alle "// Kommentare" durch "/* Kommentare */" ersetzen
Das übernehme ich, genau wie ULONG ... ersetzen durch uint32_t usw., obwohl ich sowohl ULONG als auch "// comment" bevorzuge.
-
// ist perfektes C99. Aber wenn du dem Compiler das nicht sagst, geht er eben davon aus, dass du C89 schreiben möchtest und meckert.
-
Ich bevorzuge auch "// ...", aber wenn man -ansi will, dann ist muss man eben "/* ... */" nehmen.
Wobei ANSI wohl "C90" entspricht und damit ein älterer Standard als C99 ist. Also ich an eurer Stelle würde die Kommentare so lassen und -std=c99 oder -std=gnu99 nehmen, immerhin ist C99 inzwischen auch schon zehn Jahre alt - wenn es auch nicht komplett umgesetzt ist, so müssten doch zumindest die Zeilenkommentare ("//") in allen Compilern drin sein, die C99 zumindest ansatzweise unterstützen.
-
edit: ich hab nichts gesagt^^
-
Danke für den Tipp. Denn da ich die C++-Kommentare nicht als schädlich erachte, also -std=gnu99 anstelle -ansi. OK?
Daraus folgt:
Muss: -std=gnu99 -Werror -Wall
Ziel1: -Wextra
Ziel2: -pedanticCFLAGS= -std=gnu99 -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude
Läuft beim Kernel fehlerfrei durch.
Akzeptiert?
Bezüglich c99 (vs. gnu99) wird folgender Fehler angezeigt:
i586-elf-gcc -std=c99 -Werror -Wall -O -ffreestanding -fleading-underscore -nost dlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude -c -o isrs.o isrs.c isrs.c: In function 'fault_handler': isrs.c:97: error: 'asm' undeclared (first use in this function) isrs.c:97: error: (Each undeclared identifier is reported only once isrs.c:97: error: for each function it appears in.) isrs.c:97: error: expected ';' before 'volatile' mingw32-make: *** [isrs.o] Error 1
-
Das Schlüsselwort asm gibt es in c99 nicht, sondern ist eine GNU Extension. __asm__ sollte bei beiden gehen.
-
Nach Austausch aller asm gegen __asm__ läuft im Kernel auch -std=c99 glatt durch.
Daher können wir problemlos nach der Linie
Muss: -std=c99 -Werror -Wall
Ziel1: -Wextra
Ziel2: -pedanticverfahren.
Was beinhaltet -Wextra genau?
-
Erhard Henkes schrieb:
Was beinhaltet -Wextra genau?
Von http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
-Wextra
This enables some extra warning flags that are not enabled by -Wall. (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)-Wclobbered
-Wempty-body
-Wignored-qualifiers
-Wmissing-field-initializers
-Wmissing-parameter-type (C only)
-Wold-style-declaration (C only)
-Woverride-init
-Wsign-compare
-Wtype-limits
-Wuninitialized
-Wunused-parameter (only with -Wunused or -Wall)Die meisten sind auf der Seite auch erklärt. Zusammen mit -Werror sind da welche bei, die ich während des Programmierens recht nervig finde. So sorgt -Wunused-parameter für Fehler wenn in einer Funktion nicht jeder Parameter verwendet wurde. Gerade wenn man temporär eine Funktion schreibt, die noch nicht den vollen Funktionsumfang hat, stößt man da oft drauf.
-
Ich finde alle Schalter -Wall -Wextra -Werror -pedantic ok. Man muss sich nur auf ein -std= einigen. Und ich würde c89 bevorzugen. Meine Argumente dafür wären:
- Kommentare mit // in C-Programmen sind ein Dorn im Auge
- Warnungen wie "Fehler: ISO-C90 verbietet gemischte Deklarationen und Code" bedeuten, der Programmierer weiss nicht, wie viele lokale Variablen in der Funktion verwendet werden. Pi mal Daumen Regel sagt, maximal sieben lokale Variablen...
- Alle Compiler heutzutage können c89 - bedeutet u.a. "bessere" Portabilität des Codes (unter Windows z.B. wird portabilität klein geschrieben ;), Windows läuft ja nur auf x86 ab Pentium II oder so, Linux z.B. läuft auf alpha, arm, avr32, blackfin, cris, frv, h8300, i386, ia64, m32r, m68k, m68knommu, microblaze, mips, mn10300, parisc, powerpc, s390, sh, sparc, um, x86, xtensa, ich gebe zu, habe bloss linux/arch Inhalt wiedergegeben, aber man scheint unter Linux irgendwas doch anders zu machen, als unter Windows...)Ansonsten - egal, Hauptsache, alle einigen sich auf einen -std= Schalter
-
Kommentare mit // in C-Programmen sind ein Dorn im Auge
Einem C++-Programmierer fällt das überhaupt nicht negativ auf. C99 ist vor allem modernes C:
Mit C99 flossen einige aus C++ bekannte Erweiterungen in die Sprache C ein, zum Beispiel das Schlüsselwort inline und die Möglichkeit, Variablen innerhalb der for-Anweisung zu deklarieren.
Die Deklaration innerhalb der for-Schleife würde ich auch sehr begrüßen. Das ist wirklich sinnvoll! Daher bitte ich um Zustimmung für -std=c99.
http://de.wikipedia.org/wiki/Varianten_der_Programmiersprache_C#C99
-
Erhard Henkes schrieb:
Die Deklaration innerhalb der for-Schleife würde ich auch sehr begrüßen. Das ist wirklich sinnvoll!
Ich weiss nicht, ob es sinnvoll ist. Dieses "Feature" hat ja, glaube ich, dazu geführt, dass Code, der z.B. unter MSVS sauber kompiliert, unter anderen Compilern aber nicht, weil unter MSVS konnten/können(?) die Variablen, die in for() deklariert wurden, ausserhalb der for() Schleife doch benützt werden (was ja nicht erlaubt ist)...
-
abc.w schrieb:
Erhard Henkes schrieb:
Die Deklaration innerhalb der for-Schleife würde ich auch sehr begrüßen. Das ist wirklich sinnvoll!
Ich weiss nicht, ob es sinnvoll ist. Dieses "Feature" hat ja, glaube ich, dazu geführt, dass Code, der z.B. unter MSVS sauber kompiliert, unter anderen Compilern aber nicht, weil unter MSVS konnten/können(?) die Variablen, die in for() deklariert wurden, ausserhalb der for() Schleife doch benützt werden (was ja nicht erlaubt ist)...
MSVC ist inzwischen repariert.
Und vorher haben wir uns immer beholfen mit dem Bugfix#define for if(false){}else for
-
Was ist eigentlich der Unterschied zwischen "c99" und "gnu99"?
-
Badestrand schrieb:
Was ist eigentlich der Unterschied zwischen "c99" und "gnu99"?
gnuXX ist cXX + GNU Extensions. Die GNU Extensions stehen auf http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html