Ist es richtig, dass mit "static 1" dem Compiler lediglich mitgeteilt
wird, dass mindestens ein Argument übergeben wird. Was passiert wenn
keins übergeben wird. Dann würde er doch auch ohne diese Angabe
meckern..
Gruß
Dennis
Volle schrieb:> nimm dein Buch und schlage Array nach
Das kommt aus einem Buch und Arrays kenne ich sehr gut.
Aber:
Absatz 5.1.2.2.1 in N1124 erwähnt es nicht explizit und ich habe noch
keinen Quelltext (weder kommerziell noch OSS) gesehen wo es so gemacht
wird.
Ich hoffe ich bekomme nie im Leben diese Arroganz zu behaupten alles zu
kennen...
Dennis S. schrieb:> Absatz 5.1.2.2.1 in N1124 erwähnt es nicht
Aber 6.7.6.2.1 und 6.7.6.3.7 in N1570 (C11):
> In addition to optional type qualifiers and the keyword static, the [> and ] may delimit an expression or *. [...] The optional type qualifiers> and the keyword static shall appear only in a declaration of a function> parameter with an array type, and then only in the outermost array type> derivation.> A declaration of a parameter as ‘‘array of type’’ shall be adjusted to> ‘‘qualified pointer to type’’, where the type qualifiers (if any) are> those specified within the [ and ] of the array type derivation. If the> keyword static also appears within the [ and ] of the array type> derivation, then for each call to the function, the value of the> corresponding actual argument shall provide access to the first element> of an array with at least as many elements as specified by the size> expression.
> int main ( int argc , char * argv [ argc +1]) ;
Das kann doch nicht klappen.
argc stellt erst zur Laufzeit einen Wert zur Verfügung.
Damit kann man aber kein Array deklarieren.
NurEinGast schrieb:> argc stellt erst zur Laufzeit einen Wert zur Verfügung.> Damit kann man aber kein Array deklarieren.
Doch, kann man - als Funktionsargument. Weil es vollkommen egal ist,
welche Länge da drinsteht, das verflacht ohnehin zu einem Pointer.
NurEinGast schrieb:> Egal ist es - aber mein Compiler mag so was nicht.....
Dann einfach mal die Dokumentation des Compilers lesen und den Support
für C11 einschalten.
NurEinGast schrieb:> Egal ist es - aber mein Compiler mag so was nicht.....
Kommt vielleicht auch drauf an, ob er erst das wegwirft, was in den
eckigen Klammern steht (weil: irrelevant), oder ob er den Inhalt erst
auswertet (und damit scheitert).
Aber, ja, die main() habe ich auch noch nie auf so eine Weise deklariert
gesehen. Normal ist
Gerhard schrieb:> müsste argc nicht zur Compilezeit bekannt sein für dieses Konstrukt?
In einem Funktionsparameter ist das erlaubt, wird aber einfach ignoriert
(aus historischen Gründen). Sinnvoll wäre es nur zur Dokumentation, ist
aber natürlich missverständlich.
In C11 kann man "static" hinzufügen, das heißt dann "ich meine es
ernst".
Nop schrieb:> Aber, ja, die main() habe ich auch noch nie auf so eine Weise deklariert> gesehen.
Das Gefühl habe ich auch. Aber da ich nicht jeden Quellcode der Welt
kenne...
NurEinGast schrieb:> Erstaunlich - wieder was gelernt.
Das ist der Grund warum ich gerade "Modern C" lese. Ob man will oder
nicht: die Praktiken in der Industrie sind dann ja doch oft eher
"anachronistisch".. oder "bewährt" je nach dem wie bereit man ist sich
auf Neues einzulassen. :-D
Clemens L. schrieb:> wird aber einfach ignoriert (aus historischen Gründen).
Genauer gesagt deswegen, weil in C die Länge eines Arrays nicht
Bestandteil des Arrays selber ist und andererseits aber bei
Funktionsaufrufen nur der Pointer auf das erste Array-Element übergeben
wird.
> Sinnvoll wäre es nur zur Dokumentation
Nichtmal das, denn wie lang das Arrays ist, das legt ja nicht die
aufgerufene Funktion fest, sondern der Aufrufer, weil der ja den
Speicherplatz auch bereitstellen muß.
Zudem tendiert diese Art der Doku besonders schnell zum verrotten, weil
die Längenangabe da ja egal ist und somit bei Änderung im Aufrufer auch
nichts weiter auffällt. Man hat dann sehr schnell das Einzige, was
schlimmer als fehlende Doku ist - falsche Doku.
NurEinGast schrieb:> Erstaunlich - wieder was gelernt.>> "Variable-length arrays" in C99.
Vorsicht, das ist hier IMO eine Verwechslungsfalle. Die Syntax wird
aufgrund der VLAs akzeptiert, aber das Element selber ist kein VLA, weil
es als Funktionaparameter gar nicht erst ein Array ist.
>> Das return ist übrigens schon ein out-of-bounds-access. Wenn a die Größe> des Arrays ist, dann reichen seine Elemente von 0 bis a-1.> If the keyword static also appears within the [ and ] of the array> type derivation, then for each call to the function, the value of the> corresponding actual argument shall provide access to the first element> of an array with at least as many elements as specified by the size> expression.
Gibt also nur eine Untergrenze an, keine Obergrenze.
Dennis S. schrieb:> Volle schrieb:>> nimm dein Buch und schlage Array nach>> Das kommt aus einem Buch und Arrays kenne ich sehr gut.
dann wüstest du aber das [ ] immer im Zusammenhang mir Arrays
auftauchen
Früher, als man noch Kommandozeilenprogramme geschrieben hat
so ganz ohne Fenster und Maus
hat gute jeder Entwickler seinen eigenen Parser für argv in der
Schublade
den er für alle seinen eigenen Progrämmchen verwendet hat. Für jedes
Programm erweitert und verbessert hat.
Johann L. schrieb:> Gibt also nur eine Untergrenze an, keine Obergrenze.
Dann ist es ein kein zwingender, aber ein möglicher
out-of-bounds-access, weil das Array "p" nur mindestens "a" Elemente
haben muß. Es sind also auch genau "a" Elemente zulässig, und dann ist
es out of bounds.
Nop schrieb:> Johann L. schrieb:>>> Gibt also nur eine Untergrenze an, keine Obergrenze.>> Dann ist es ein kein zwingender, aber ein möglicher> out-of-bounds-access, weil das Array "p" nur mindestens "a" Elemente> haben muß. Es sind also auch genau "a" Elemente zulässig, und dann ist> es out of bounds.
Mag sein. Aber dann hätte ich zumindest eine mögliche Warnung erwartet,
die darauf hinweist. Ansonsten sehe ich keinen Vorteil dieses
Konstrukts, auch nicht, wie man das für effizienteren Code verwursten
könnte.
Ja gut, da hätte man eine Warnung nehmen können.
Aber -Wvla ist sinnlos, weil das immer warnt, wenn VLAs im Code benutzt
werden - und zwar unabhängig davon, ob sie korrekt benutzt werden oder
nicht. So erklärt sich auch die Warnung, die da kam.
Nop schrieb:> Ja gut, da hätte man eine Warnung nehmen können.>> Aber -Wvla ist sinnlos, weil das immer warnt, wenn VLAs im Code benutzt> werden - und zwar unabhängig davon, ob sie korrekt benutzt werden oder> nicht. So erklärt sich auch die Warnung, die da kam.
Verstehe ich immer noch nicht. Ob es sich bei einem Array um ein VLA
handelt kann doch bestenfalls der Aufrufer wissen?
Meinem Verständnis nach ist ein VLA eine Array, dessen Größe zur
Compilezeit unbekannt ist und das auf dem Stack angelegt wird, z.B.
1
externvoidbar(int*);
2
3
voidfunc(size_ts)
4
{
5
inta[s];
6
bar(a);
7
}
oder per alloca.
Arrays auf dem Heap, die z.B. per malloc et al. angelegt werden, sind
demnach keine VLAs.
Volle schrieb:> dann wüstest du aber das [ ] immer im Zusammenhang mir Arrays> auftauchen
Ja... wie gesagt tue ich das sehr gut. Es geht hier aber trotzdem um die
ungewöhnliche Deklaration von main().
Wie hoch ist der Prozentsatz der dir bekannten Projekte, die diese Art
der Deklaration nutzen? Wäre ja mal interessant.
Gruß
Dennis
Johann L. schrieb:> Verstehe ich immer noch nicht.
Die Warnung ist nur dazu da, daß GCC eben warnt, daß das Feature der
VLAs überhaupt benutzt wird, so lese ich die GCC-Doku jedenfalls.
> Ob es sich bei einem Array um ein VLA> handelt kann doch bestenfalls der Aufrufer wissen?
In Deinem Beispiel nicht, denn der Aufrufer muß nichtmal ein Array
bereitstellen, sondern nur einen Pointer, der auf den Beginn eines
Speicherbereiches von mindestens "a" ints zeigt.
> Meinem Verständnis nach ist ein VLA eine Array, dessen Größe zur> Compilezeit unbekannt ist
Ja. Aber im vorliegenden Beispiel war das ja als Funktionsparameter, wo
es außerhalb der Funktion schon angelegt worden sein muß.
> und das auf dem Stack angelegt wird
Das sagt der C-Standard nicht, weil er den Begriff des Stacks gar nicht
kennt. GCC implementiert VLAs auf dem Stack, aber er dürfte das
theoretisch auch per Heap implementieren. Wäre aber wohl ineffizienter.
C selber ist das jedenfalls egal, wichtig ist nur, daß VLAs nur in
Funktionen angelegt werden können, nicht mit storage class "extern" oder
"static", und daß sie nicht initialisiert sind, was die effiziente
Implementation über den Stack erst ermöglicht.
> Arrays auf dem Heap, die z.B. per malloc et al. angelegt werden, sind> demnach keine VLAs.
Per malloc werden ohnehin keine Arrays angelegt, sondern das sind
Pointer auf allozierte Speicherbereiche.
Wesentlicher Unterschied:
Was ist jetzt eigentlich die Antwort auf die Frage des Themenerstellers?
Dass es zwar nicht falsch (weil vom Compiler akzeptiert), aber doch eher
blödsinnig ist, die main-Funktion so zu deklarieren?
Mark B. schrieb:> Dass es zwar nicht falsch (weil vom Compiler akzeptiert), aber doch eher> blödsinnig ist, die main-Funktion so zu deklarieren?
Ich sehe mich zumindest darin bestätigt, dass es sehr ungewöhnlich ist.
F. F. schrieb:> Dennis S. schrieb:>> int main ( int argc , char * argv [ argc +1]) ;>> Ich glaube nicht, dass das da so steht. :-)
Falls du dich auf das Semikolon beziehst: JEDER hier hat doch verstanden
worum es geht... Wahrscheinlich habe ich irgendwas vor dem Kopieren
falsch markiert. Mea Culpa.
Gruß
Dennis S. schrieb:> Wie hoch ist der Prozentsatz der dir bekannten Projekte, die diese Art> der Deklaration nutzen? Wäre ja mal interessant.
80% der Programe unter Dos Windows Unix (und was davon abstammt)
0% in den embeded Programmen, denn da steht startOS in main und kann
main keie Parameter übergeben
Übrigens auch in den Perl und Java Programmen
jedes gute Programm sollte aus der Kommandozeile auf den Parameter -?
oder -h regieren. Und wenn es nur anzeigt wer der Schuldige ist.
in ISO/IEC 9899:2011
5.1.2.2.1 Programm startup
int main(int argc, char *argv[]) { /* ... */ }
or equivalent; or in some other implementation-defined manner.
int can be replaced by a typedef name defined as int, or the type of
argv can be written as char ** argv, and so on.
Volle schrieb:> int can be replaced by a typedef name defined as int, or the type of> argv can be written as char ** argv, and so on.
Mit welchem Sinn?
Das muss ich mir bei Gelegenheit mal ganz durchlesen.
F. F. schrieb:> Volle schrieb:>> int can be replaced by a typedef name defined as int, or the type of>> argv can be written as char ** argv, and so on.>> Mit welchem Sinn?
Den darf sich jeder selber aussuchen. Wer - aus welchem Grund auch immer
- lieber mit typedefs statt direkt mit den eingebauten Typnamen arbeiten
will, hat auf diese Weise zumindest die Erlaubnis dazu und wird nicht
gezwungen, wörtlich "int" hinzuschreiben. Bei char ** argv das gleiche.
Da wird einfach nur gesagt, dass die angegebene Zeile nicht 100%
wörtlich so hingeschrieben sein muss, sondern nur zu 100% äquivalent
dazu sein muss.
Volle schrieb:> 80% der Programe unter Dos Windows Unix (und was davon abstammt)> 0% in den embeded Programmen, denn da steht startOS in main und kann> main keie Parameter übergeben
Kannst du ein paar Projekte verlinken (Github). Ich kann es noch nicht
so recht glauben. Du hast nicht vergessen, dass es um die "argc + 1"
geht, oder?
Gruß
Dennis
Ich meine die gesamte DOS Command Parameterübergabe hat so die Argumente
übergeben bekommen Stichwort Commandzeilenparameter.
So konnte der command.com Parameter aus der Commandline an die main in
"*.cmd" übergeben.
Namaste
Nop schrieb:> Im C-Standard - Arrays sind eben keine Pointer.
Danke! Das Arrays keine Arrays sind war mir theoretisch bekannt, konnte
mir aber kein Beispiel vorstelleb wo das relevant ist.
In den meisten Fällen "zerfallen" Array-Typen in Zeiger-Typen, Ausnahmen
sind der sizeof-Operator und der Address-Operator:
1
#include<assert.h>
2
3
voidf1(constchar*p){
4
charfirst=p[0];
5
}
6
7
voidf2(constchar(*p)[10]){
8
charfirst=(*p)[0];// Achtung
9
}
10
11
intmain(){
12
constchars1[]="abc";
13
constchars2[10]="abc";
14
15
f1(s1);
16
f2(s1);// decay
17
18
f1(s2);
19
f2(s2);// decay
20
21
f1(&s2);// incompatible
22
f2(&s2);// ok!!! Kein Zerfallen [1]
23
24
assert(s1==&s1);// gleiche Adressen
25
assert(s2==&s2);
26
27
constchar*cs1=s1;
28
constchar*cs2=s2;// decay
29
30
f1(cs1);
31
f2(cs2);// decay
32
33
assert(sizeof(s1)==4);
34
assert(sizeof(s2)==10);
35
36
assert(sizeof(cs1)==sizeof(char*));
37
assert(sizeof(cs2)==sizeof(char*));
38
}
[1] hier ist zu beachten, dass der Address-Operator den Typ nicht
zerfallen lässt.
Wie man sieht, ist die Adresse des ersten Elementes und die Adresse des
Arrays vom Wert identisch, aber der Typ ist eben unterschiedlich, dass
muss dann in f2() beachtet werden.
D.h. beim "normalen" Aufruf einer Funktion mit einem Array-Bezeichner
wird als Wert die Adresse des ersten Elementes übergeben und der Type
zerfällt in Zeiger-auf-Elementtyp. So geht dann die Längeninformation in
der aufgerufenen Funktion verloren.
Achim S. schrieb:> Also hat jetzt jemand ein Beispiel, wo main so deklariert wird??>> Dennis S. schrieb:>> int main ( int argc , char * argv [ argc +1]) ;
Das übersetzt der Compiler zwar, aber die nicht-konstante
Dimensionsangabe wird nicht beachtet!
Dem main() geht ja ein exec() voraus und hier zerfällt jeder Array-Typ
schon in einen Zeiger-Typ. Deswegen ist die Dimensionierung einfach
sinnlos.
Das argv-Array hat in der Tat argc+1 Elemente, denn das letzte Element
ist als Sentinel der Wert 0 bzw. NULL.
Wilhelm M. schrieb:> In welchem Projekt hast Du das denn gefunden?>> Die möglichen Signaturen von main() sind:> int main() in C++ bzw. int main(void) in C
Sowohl in C, als auch in C++ macht das für main überhaupt keinen
Unterschied.
> int main(int, const char**)
Diese ist äquivalent zu der hier diskutierten Variante.
> int main(int, const char**, const char** e) // e = C-String Array der> env-Variablen
Diese Version ist systemspezifisch und gibt es in der ISO-Norm nicht.
Sie ist aber auch nicht verboten.
Rolf M. schrieb:> Wilhelm M. schrieb:>> In welchem Projekt hast Du das denn gefunden?>>>> Die möglichen Signaturen von main() sind:>> int main() in C++ bzw. int main(void) in C>> Sowohl in C, als auch in C++ macht das für main überhaupt keinen> Unterschied.
(C): int foo(); deklariert eine Funktion mit variabler Parameterliste
(C): int foo(void); deklariert eine Funktion mit leerer Parameterliste
(C++): int foo(); deklariert eine Funktion mit leerer Parameterliste
siehe auch: http://en.cppreference.com/w/c/language/main_function>>> int main(int, const char**)>> Diese ist äquivalent zu der hier diskutierten Variante.
Habe auch nichts anderes behauptet.
>>> int main(int, const char**, const char** e) // e = C-String Array der>> env-Variablen>> Diese Version ist systemspezifisch und gibt es in der ISO-Norm nicht.> Sie ist aber auch nicht verboten.
Stimmt nicht. Siehe auch:
http://en.cppreference.com/w/c/language/main_function
Wilhelm M. schrieb:> (C): int foo(); deklariert eine Funktion mit variabler Parameterliste> (C): int foo(void); deklariert eine Funktion mit leerer Parameterliste
Ich weiß, was der Unterschied in C bei Deklarationen mit und ohne void
in der Parameterliste ist. Das ist relevant für den Aufrufer der
Funktion. Aber main() wird nicht von mir, sondern automatisch vom
Startup-Code aufgerufen, daher spielt das da keine Rolle. Deshalb
schrieb ich oben:
>> [...] macht das für main überhaupt keinen Unterschied.> (C++): int foo(); deklariert eine Funktion mit leerer Parameterliste
Das (void) ist in C++ aber nicht verboten. Es macht einfach nur das
gleiche wie eine leere Liste.
>>> int main(int, const char**)>>>> Diese ist äquivalent zu der hier diskutierten Variante.>> Habe auch nichts anderes behauptet.
Dann verstehe ich nicht, was du mit deiner Mail sagen wolltest.
>>> int main(int, const char**, const char** e) // e = C-String Array der>>> env-Variablen>>>> Diese Version ist systemspezifisch und gibt es in der ISO-Norm nicht.>> Sie ist aber auch nicht verboten.>> Stimmt nicht.
Doch, tut es.
> Siehe auch:> http://en.cppreference.com/w/c/language/main_function
Hä? Das bestätigt doch, dass meine Aussage stimmt:
other_parameters - Implementations may allow additional forms of the
main function. A very common extension is passing a third argument of
type char*[] pointing at an array of pointers to the execution
environment variables.
Diese beiden Sätze haben doch exakt die gleiche Aussage wie das, was ich
oben geschrieben habe.
Rolf M. schrieb:>> Das (void) ist in C++ aber nicht verboten. Es macht einfach nur das> gleiche wie eine leere Liste.
Habe ich auch nicht behauptet.
>>> Diese Version ist systemspezifisch und gibt es in der ISO-Norm nicht.
Doch, steht doch da.
> Diese beiden Sätze haben doch exakt die gleiche Aussage wie das, was ich> oben geschrieben habe.
Nein, Du hast geschrieben, dass es sie im Standard nicht gibt! Der
Standard kennt mindestens 3 Varianten:
Wilhelm M. schrieb:> Rolf M. schrieb:>>>> Das (void) ist in C++ aber nicht verboten. Es macht einfach nur das>> gleiche wie eine leere Liste.>> Habe ich auch nicht behauptet.
Du hattest oben explizit unterschieden zwischen C und C++ und angemerkt,
dass es in C mit und in C++ ohne void zu schreiben ist. Ich hab nur
darauf hingewiesen, dass diese Unterscheidung nicht nötig ist.
Wilhelm M. schrieb:>> Diese beiden Sätze haben doch exakt die gleiche Aussage wie das, was ich>> oben geschrieben habe.>> Nein, Du hast geschrieben, dass es sie im Standard nicht gibt!
Das ist auch richig.
> Der Standard kennt mindestens 3 Varianten:> int main (void) { body } (1)> int main (int argc, char *argv[]) { body } (2)> int main (int argc, char *argv[] , other_parameters ) { body } (3)> /* another implementation-defined signature */ (4)
Ah, jetzt sehe ich erst, dass es hier (1) bis (4) gibt. Ich hatte (3)
und (4) als eins gelesen. Die Variante (3) gibt es so in ISO C nicht.
Wozu auch? Sie ist eine Form der Variante (4).
Hier mal der original-Wortlaut aus dem letzten Draft von C11, der
praktisch unverändert schon immer so enthalten ist:
**********************************************************************
The function called at program startup is named main. The implementation
declares no prototype for this function. It shall be defined with a
return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any
names may be used, as they are local to the function in which they are
declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent or in some other implementation-defined manner.
**********************************************************************
Da ist nirgends die Variante 3 explizit erwähnt.
Wilhelm M. schrieb:> In welchem Projekt hast Du das denn gefunden?
Das stammt (wie oben schon mal irgendwo geschrieben) aus dem
(Online-)Buch "Modern C Programming). Aber leider geht durch das Kapern
fremder Threads schon sehr die Übersicht verloren.
Sonst hätte "Volle" ja sicherlich die Frage schon beantwortet... ;-)
Dennis S. schrieb:> Wilhelm M. schrieb:>> In welchem Projekt hast Du das denn gefunden?>> Das stammt (wie oben schon mal irgendwo geschrieben) aus dem> (Online-)Buch "Modern C Programming). Aber leider geht durch das Kapern> fremder Threads schon sehr die Übersicht verloren.
Hast Du mal den Link? Es gibt gefühlt tausend solcher Online-Bücher ...
Beitrag "Re: Deklaration von main()"
Hier hab ich's noch mal gefunden: TONY ZHANG "Teach Yourself 24 Lessons
C in 24 hours"
Hatte ich mich doch richtig erinnert.
Namaste
Hier gibt es das Buch zum Download:
http://icube-icps.unistra.fr/img_auth.php/d/db/ModernC.pdf
Der Autor des Buchs verwendet für einige Deklartionen gewisse
Schreibweisen, die er zu Beginn erläutert und begründet. In diesen
Schreibweisen tauchen z.T. Dinge (wie bspw. die Größenangabe beim
argv-Array) auf, die nicht an den Compiler (der sie einfach ignoriert),
sondern an den Programmierer gerichtet sind, und zum besseren
Verständnis des Codes beitragen sollen.
Er sich sich aber bewusst, dass einige Programmierer anders denken als
er und schickt deswegen eine Warnung voraus:
1
Warning to experienced C programmers. If you already have some
2
experience with C programming, this may need some getting used to. Here
3
are some of the things that may provoke allergic reactions. If you
4
happen to break out in spots when you read some code here, try to take a
5
deep breath and let it go.
Bis auf die Stroustrupsche Pointerdeklaration¹ finde ich seine
Vorschläge eigentlich auch ganz sinnvoll.
—————————————
¹) Also "char* name;" anstelle von "char *name;". Aber diese Thema wurde
schon zur Genüge ausdiskutiert. Manche mögen's eben lieber so, andere
lieber so.
Sollte noch jemand Interesse haben suche ich die CD zum Buch und stelle
das Beispiel ein aber.
Soviel ist klar, mit der Übergabe einer Arrayadresse vom Typ char und
der
und der Grösse des Arrays als Parameter lassen sich Parameter von
Programmdatei zu Programmdatei übergeben ohne das main(*,*) zur Laufzeit
des Compilers Kenntniss davon haben muss ob überhaupt wissen mus ob und
wieviele Parameter übergeben werden sollen
so waren diverse zusätzliche DOS-Command-Befehle nachträglich
integrierbar ohne command.sys und command.com neu compilieren zu müssen.
Ich tippe bei Unix sieht es ähnlich aus?
Namaste
Achim S. schrieb:> Winfried J. schrieb:>> Hatte ich mich doch richtig erinnert.>> Glückwunsch. Aber haben Deine beiden Beiträge hier irgendwas mit dem> Thread zu tun?
Ich denke sie beantworten ziemlich exakt die Anfangsfragefrage des TO.
Wobei sein Beispiel wohl eine konkrete Variante zu der von mir im Buch
wiedergefundenen etwas allgemeineren Darstellung ist.
Namaste
Winfried J. schrieb:> Achim S. schrieb:>> Winfried J. schrieb:>>> Hatte ich mich doch richtig erinnert.>>>> Glückwunsch. Aber haben Deine beiden Beiträge hier irgendwas mit dem>> Thread zu tun?>> Ich denke sie beantworten ziemlich exakt die Anfangsfragefrage des TO.>> Wobei sein Beispiel wohl eine konkrete Variante zu der von mir im Buch> wiedergefundenen etwas allgemeineren Darstellung ist.
Schau Dir doch noch mal die ursprüngliche Frage an!!!
o.k. ich dachte er kommt mit dem Konstrukt grundsätzlich nich ins
Benehmen.
Wie du schon schriebst "Katz mag mais"
Wohl war der Autor versucht sprechenden Code zu schreiben statt sich der
Kommentarfunktion zu bedienen. Klar dass, dies bei einigen
schwarz-weis-Denkern zu Brechreiz führt. Aber das ist ja das tolle an C
jeder darf so schreiben das niemand es lesen kann, oder so das es auch
ein Anfänger verstehen könnte. ;)
Ich habe darin gar kein Problem gesehen. und deshal wohl auch die Frage
anders interpretiert als ihr.
sorry dafür
Namaste
Yalu X. schrieb:> Hier gibt es das Buch zum Download
Habe mal rein geschaut.
Sehr schön: Rule B.
:-)
Deswegen mag ich englische Fachbücher so gern.
(Obwohl ich gar kein Englisch kann, wie der Naga (Ableitung von
Teenager, ist dann Naga geworden, weil es die wirklich gibt) nach einem
halben Jahr Amerika meinte. Eine halbe Stunde später musste er
feststellen, dass er es offensichtlich auch nicht kann :-))
Dennis S. schrieb:> Wilhelm M. schrieb:>> Hast Du mal den Link? Es gibt gefühlt tausend solcher Online-Bücher ...>> https://gustedt.wordpress.com/2016/11/25/modern-c-is-now-feature-complete/
Wenn man den Text dort (S.14) liest, ist doch alles erläutert. Der Autor
sagt ja auch, dass das, was er schreibt, zu den oben von mir genannten
Signaturen äquivalent ist und er seine Schreibweise "nur" gewählt hat,
um die Annahmen (pointer != 0, mindestens argc + 1 Elemente, etc, ...)
klarer auszudrücken. Das gilt auch für seine Schreibweise von
Funktionszeigern.
Leider wird das ja alles vom C-Compiler ignoriert. Insofern nützt es gar
nichts (ausser vielleicht den flüchtigen Leser zu verwirren).
Ich habe nicht nachgeschaut, ob er den "Zerfall" (decay) von
Arraybezeichnern oder Funktionsbezeichnern auch erläutert: das wäre m.E.
das wichtigere (s.o. mein Post zu dem Thema).
Und da kann ich mir leider die Bemerkung nicht verkneifen, dass in C++
solche (und viele andere Dinge) wesentlich besser sind: denn
Schnittstellen, die auf Annahmen beruhen (etwa ein C-String ist eine
zusammenhängende Folge von char-Elementen mit dem Stringendezeichen '\0'
als Sentinel) sind schlecht, weil der Compiler Verletzungen dieser
Annahmen nicht zur Compilezeit entdecken kann.
Bevor jetzt wieder der Sturm der Entrüstung losgeht: ja, natürlich
brauche ich im C++-Code auch eine freie Funktion main(int, char**), wenn
ich exec()-Parameter haben möchte...
Wilhelm M. schrieb:> Leider wird das ja alles vom C-Compiler ignoriert. Insofern nützt es gar> nichts (ausser vielleicht den flüchtigen Leser zu verwirren).
Auch Kommentare werden vom Compiler ignoriert (nicht nur in C, sondern
sogar in C++). Sind auch sie deswegen völlig nutzlos? ;-)
Ich finde es durchaus sinnvoll, bei mehreren äquivalenten Schreibweisen
jeweils diejenige zu verwenden, die die Absicht des Programmierers am
besten ausdrückt.
So würde ich bspw. eine Funktion, die einen Pointer auf ein einzelnes
int entgegennimmt, so deklarieren:
1
voidfunc(int*a);
Wenn sie hingegen ein Array (d.h. einen Pointer auf dessen erste
Element) erwartet, würde ich die Array-Syntax bevorzugen, auch wenn
semantisch kein Unterschied besteht:
Yalu X. schrieb:> Wilhelm M. schrieb:>> Leider wird das ja alles vom C-Compiler ignoriert. Insofern nützt es gar>> nichts (ausser vielleicht den flüchtigen Leser zu verwirren).>> Auch Kommentare werden vom Compiler ignoriert (nicht nur in C, sondern> sogar in C++). Sind auch sie deswegen völlig nutzlos? ;-)
Es gibt zwei Dinge bei Kommentaren zu beachten:
1) Kommentare altern anders als der sie umgebende Code.
2) Kommentiere nur das, was der Code nicht sagt, und nicht das, was der
Code nicht sagen kann.
zu 1) Bessere Kommentare sind Assertionen.
zu 2) Erst wenn man den Code nicht mehr expressiver gestalten kann,
sollte man einen Kommentar in Betracht ziehen.
> Ich finde es durchaus sinnvoll, bei mehreren äquivalenten Schreibweisen> jeweils diejenige zu verwenden, die die Absicht des Programmierers am> besten ausdrückt.
Natürlich (s.a. 2)!
> So würde ich bspw. eine Funktion, die einen Pointer auf ein einzelnes> int entgegennimmt, so deklarieren:>>>
1
>voidfunc(int*a);
2
>
>> Wenn sie hingegen ein Array (d.h. einen Pointer auf dessen erste> Element) erwartet, würde ich die Array-Syntax bevorzugen, auch wenn> semantisch kein Unterschied besteht:>>>
1
>voidfunc(inta[]);
2
>
Klar, kann man so machen: jeder findet seine eigenen Code-Konventionen
eh am besten.
Trotzdem fehlt in func(int a[]) die Längenangabe!
Trotzdem kann der Datentyp keine Aussage über den Unterschied machen.
Und es ändert nichts an der Tatsache, dass man möglichst viel Semantik
in die Datentypen legen sollte, damit der Compiler besser prüfen kann.
Kosten tut das ja bei C++ zur Laufzeit nichts.
Wilhelm M. schrieb:> Trotzdem kann der Datentyp keine Aussage über den Unterschied machen
Das stimmt zwar ... aber nur so halb. Statische Codeanalyse wie Lint
könnte dementsprechend konditioniert werden.
a.s schrieb:> Wilhelm M. schrieb:>> Trotzdem kann der Datentyp keine Aussage über den Unterschied machen>> Das stimmt zwar ... aber nur so halb. Statische Codeanalyse wie Lint> könnte dementsprechend konditioniert werden.
Natürlich kann ich mir für jedes fragwürdige Konstrukt einen CodeChecker
schreiben: clang-libanalyze macht das ja leicht möglich. Auch gleich mit
der Möglichkeit, das Konstrukt dann umzuschreiben ...
Aber: warum sollte ich das tun?
Besser auf eine Sprache umsteigen, die das gleiche kann aber
gleichzeitig wesentlich expressiver ist (C++). Und das bedeutet ja
nicht, dass ich dann OOP im engeren Sinne nutzen muss! Ich kann genauso
prozedural bleiben wie in C und nur an der ein oder anderen Stelle
besser werden.