Hallo Leute,
in dem Faden
Beitrag "Welche Programmiersprache lernen? (C, Phyton, Lisp, Swift, Smalltalk?)"
schrib Vril:
Vril schrieb:> Marc E. schrieb:>> http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/>> Da wird dir C sehr ausführlich erklärt sehr zum empfehlen.>> Nein, dieses Buch sollte man nicht empfehlen. Es ist grottenschlecht und> voller Fehler.
Ich würde gerne genauer wissen, wieso das Buch grottenschlecht ist und
ein oder zwei Beispiele für Fehler genannt bekommen, weil mir diese
beiden Kritikpunkte als C-Interessierter bei der Lektüre des Buches
nicht aufgefallen sind.
Hab einen:
5.2 Der Datentyp »int« (Integer)
Der Datentyp int muss, gemäß ANSI C, mindestens eine Größe von zwei Byte
aufweisen. Mit diesen zwei Bytes lässt sich ein Zahlenraum von -32768
bis +32767 beschreiben
Das Minimum ist -32767, nicht -32768, denn C unterstützt auch Systeme
die das Einerkomplement nutzen. Die allermeisten nutzen aber das
Zweierkomplement und können bis -32768.
Dr. Sommer schrieb:> Das Minimum ist -32767, nicht -32768, denn C unterstützt auch Systeme> die das Einerkomplement nutzen. Die allermeisten nutzen aber das> Zweierkomplement und können bis -32768.
Diese Info hätte ich als Author auch weggelassen, denn Einerkomplement
nutzt seit 30 Jahren niemand mehr. Das verwirrt Anfänger nur.
Dr. Sommer schrieb:> Ganz schlechter Stil, dafür nimmt man typedef
Nee, dafür nimmt man das fertige uint8_t aus dem stdint.h Header.
15.12 Attribute von Strukturen verändern (nicht ANSI C)
"Dies hängt vom Betriebssystem ab."
Eher vom Prozessor bzw. Architektur und wie der Compiler diese
unterstützt. Das OS könnte das höchstens beeinflussen indem es auf ARM
unaligned Zugriffe abschaltet.
Jim M. schrieb:> Das verwirrt Anfänger nur.
Weglassen wäre okay, aber eine *Fehl*information verwirrt noch mehr! Es
wurde nach Fehlern gefragt, nicht nach didaktischen Details, und das ist
einer. Lässt sich eindeutig im C Standard zeigen.
Jim M. schrieb:> Nee, dafür nimmt man das fertige uint8_t aus dem stdint.h Header.
Es gibt Situationen wo man Typ Aliase definiert, und dann nimmt man
typedef.
Das ganze Kapitel "16.17.3 Big Endian und Little Endian" ist falsch,
denn es gibt noch mehr Formate und durch Pointer Casts die Host
Reihenfolge zu bestimmen ist unportabel und enorm hässlich. Korrekte
Programme nutzen Bitshifts und müssen dafür die Host Order gar nicht
explizit kennen.
Es ist wie bei jedem Thema: DAS Buch gibt es (leider) nicht.
Einfach eins der bei amazon bestbewertesten kaufen und durcharbeiten,
danach nochmal ein anderes durchkauen.
Dr. Sommer schrieb:> und durch Pointer Casts die Host Reihenfolge zu bestimmen ist unportabel
nö. Cast auf char* ist explizit nach Aliasingregeln erlaubt.
Ich habe vor 30 Jahren mit C auf AT&T System V Unix begonnen -
da war der "Kernighan & Ritchie" die C-Bibel.
Dieses Standardwerk ist es eigentlich noch immer, es gibt eine
verbesserte 2. Auflage mit sehr guter Übersetzung von den Professoren
Schreiner & Janich.
Programmieren in C: Mit dem C-Reference Manual in deutscher Sprache
( Es ist die 2. Auflage aus dem Jahr 1990 vom K&R mit dem ANSI Standard
)
ISBN-10: 3446154973
ISBN-13: 978-3446154971
Der K&R ist aber nur in dieser letzten, zweiten Ausgabe (nicht Auflage)
zu empfehlen.
Der beschreibt C89 (auch "ANSI-C" genannt), also C mit
Funktionsprototypen und Typprüfungen bei Funktionsaufrufen etc.
Die ältere Ausgabe beschreibt hingegen das K&R-C, eine steinalte und
extrem fehleranfällige C-Variante. Der will man seit bald 30 Jahren
nicht mehr begegnen müssen.
Grauenerregend ist auch die deutsche Ausgabe des alten "K&R", nicht nur,
daß die Sprache so wirkt, als wäre sie mit einem Automaten übersetzt
(und daher von Deppen Leer Zeichen schon zu einer Zeit durchsetzt war,
als die unsägliche Rechtschreibreform noch nicht mal im Entstehen war),
auch die Typographie ist gräuslich - Codebeispiele sind dort in einer
schlecht lesbaren Proportionalschrift gesetzt.
Beide Bücher erschienen im Hanser-Verlag.
Leider hat sich bislang niemand die Mühe gemacht, ein qualitativ dem
zweiten K&R entsprechendes Buch zu verfassen, das all die
Weiterentwicklungen von C (C99 etc.) beschreibt.
Andererseits:
Mit C89 kann man auch heute gut auskommen. Auch heutige C-Compiler
übersetzen C89-konformen Code ohne zu murren.
MaWin schrieb:> nö. Cast auf char* ist explizit nach Aliasingregeln erlaubt.
Erlaubt ja, aber das Ergebnis ist Implementation defined, d.h. es ist
nutzlos wenn man portabel arbeiten möchte. Gerade wenn man C lernt
sollte man nicht mit plattformspezifischen Hacks anfangen sondern
erstmal nur Code schreiben, dessen Verhalten wohldefinierte ist. Zumal
es hier ja auch gar nicht nötig ist.
Rufus Τ. F. schrieb:> extrem fehleranfällige C-Variante.
Es ist immer gut sich vor Augen zu halten, dass es möglich ist noch
fehleranfälliger als mit ANSI C zu arbeiten möglich ist.
@Dr. Sommer
Die von dir genannten Beispiele sind aller eher Randthemen für einen C
Beginner.
Statt also krampfhaft irgendwelche Fehler zu suchen, die es in so einem
dicken Wälzer praktisch immer gibt wäre es deutlich hilfreicher dem TO
ein gutes Einsteigerbuch zu nennen.
Ich weiss leider keins, da ich Ansi-C in den 80gern mit dem oben
erwähnten Kernighan-Ritchie gelernt habe (ich kenne beide Auflagen) und
woweit ich mich erinnere auch da über zum Teil krasse Fehler gestolpert
bin.
Der Andere schrieb:> Die von dir genannten Beispiele sind aller eher Randthemen für einen C> Beginner.
Schon. Aber bei C steckt der Teufel im Detail. Und simple Dinge sind ja
auch nicht so oft falsch.
Der Andere schrieb:> wäre es deutlich hilfreicher dem TO ein gutes Einsteigerbuch zu nennen.
Er hat explizit nach Fehlern gefragt! Ich kenne auch keins. Hab direkt
C++ gelernt... allerdings auch nicht wirklich geradlinig.
Der Andere schrieb:> Ich weiss leider keins, da ich Ansi-C in den 80gern mit dem oben> erwähnten Kernighan-Ritchie gelernt habe (ich kenne beide Auflagen) und> woweit ich mich erinnere auch da über zum Teil krasse Fehler gestolpert> bin.
Beispiel?
Ich würde ein aktuelles C-Buch von Addison-Wesley empfehlen. Ansonsten:
die Dokumentation zum Compiler durchwälzen, das ist nie umsonst.
Zu dem Autor von dem o.g. Buch gibt es reichlich Diskussionen.
Z.B. https://www.c-plusplus.net/forum/272350
Man kann auch die 1-Stern Bewertungen bei Amazon durchlesen.
Edson schrieb:> Beispiel?
Das ist >25 Jahre her und ab und an muss ich hier auch arbeiten, die
Bücher stehen zu Hause.
Edson schrieb:> Ansonsten:> die Dokumentation zum Compiler durchwälzen
Schwerlich didaktisch gut für einen Anfänger
Stefan schrieb:> Ist das C Wikibook denn nicht gut genug? (Ich habe es nicht gelesen.)
Ein Fehler:
int ix;
short anArray[]= { 3, 6, 9, 12, 15 };
for (ix=0; ix< (sizeof(anArray)/sizeof(short)); ++ix) {
Mit int durch ein Array iterieren. Der Vergleich sollte sogar eine
Compiler Warnung produzieren.
Der Text scheint allgemein nur sehr mager und didaktisch schlecht
aufbereitet.
Dr. Sommer schrieb:> Der Text scheint allgemein nur sehr mager und didaktisch schlecht> aufbereitet.
Schade. Da C so alt und so verbreitet ist bzw. so viele Leute sich damit
wirklich gut auskennen, hätte ich ein recht gutes Wikibook erwartet.
Ubrigens: Kürzlich hatte ich mich nach einem aktuellen C++ Buch
umgesehen -- was mich zunächst verwirrt hatte, war das es "C++ Primer"
von Lippman und "C++ Primer plus" von Prata gibt. Und wirklich seltsam
ist, das das Prata-Buch bei Amazon.com sehr gut bewertet ist, in den
Foren wie etwa
http://www.cplusplus.com/forum/beginner/106097/
aber durchfällt. So langsam habe ich den Verdacht dass die Amazom-Kunden
die Bücher teils verwechselt haben.
Ich hätte mir jedenfalls fast Prata gekauft. Das Lippman-Buch scheint
ganz OK zu sein, ist aber nur C++ 11.
Auf ein aktuelles, gutes C++17 Buch muss ich wohl noch etwas warten.
Aber ich will eh nicht C++ programmieren, bloß man muss es ja oft
beherrschen für den Job und so.
Stefan schrieb:> Schade. Da C so alt und so verbreitet ist bzw. so viele Leute sich damit> wirklich gut auskennen, hätte ich ein recht gutes Wikibook erwartet.
Tja, gute Arbeit kostet Geld...
Stefan schrieb:> Ubrigens: Kürzlich hatte ich mich nach einem aktuellen C++ Buch> umgesehen
Hier eine hilfreiche Liste: https://stackoverflow.com/a/388282Stefan schrieb:> aber durchfällt. So langsam habe ich den Verdacht dass die Amazom-Kunden> die Bücher teils verwechselt haben.
Amazon Bewertungen sind oft völliger Unfug, in beide Richtungen.
Insbesondere Anfänger können die Probleme eines Buchs nicht sehen und
bewerten es dann gut, weil es ihnen Erfolgserlebnisse gegeben hat - auch
wenn die erlernten Arbeitsweisen fragwürdig sind.
Stefan schrieb:> Aber ich will eh nicht C++ programmieren, bloß man muss es ja oft> beherrschen für den Job und so.
C++ zu lernen ohne sehr viel Übung hineinzustecken klingt gewagt.
Dr. Sommer schrieb:> C++ zu lernen ohne sehr viel Übung hineinzustecken klingt gewagt.
Ja mit den Amazon-Bewertungen hast Du wohl recht.
Und zu C++ -- es nicht zu beherschen ist halt eine gewisse
Bildungslücke, und modernes C++ bietet ja auch einige interessante
Konzepte wie RAII.
Ich hatte vor ca. 8 Jahren mal mit dem Buch von Bruce Eckel mit C++
angefangen, aber er kommt halt aus der Java-Ecke und schwärmt etwas zu
viel von OOP. Und jetzt ist das Buch eh veraltet.
Ich denke Rust ist eh das modernere C++ -- werde ich aber wohl erst im
nächsten Winter richtig lernen.
Dr. Sommer schrieb:> Mit int durch ein Array iterieren. Der Vergleich sollte sogar eine> Compiler Warnung produzieren.
Das wird doch so im K&R gelehrt.
Und für diesen Zweck reicht es aus (da reicht auch ein char, ist ja das
Mikrocontrollerforum)
(sizeof(anArray)/sizeof(short)) geht auch eleganter:
(sizeof(anArray)/sizeof(*anArray))
Dirk B. schrieb:> Das wird doch so im K&R gelehrt.
Tatsächlich? Das ist bedenklich.
Dirk B. schrieb:> Und für diesen Zweck reicht es aus (da reicht auch ein char, ist ja das> Mikrocontrollerforum)
Das Wikibook bezieht sich aber nicht auf Mikrocontroller. Und char? Du
hast nie Arrays mit mehr als 127 Elementen?
"Reicht aus" ist der Feind von "Gut"... Früher oder später gehts halt
doch schief, und dann guckt man blöd. Ich finde, gerade Bücher für
Einsteiger sollten sich pingeligst an den Standard halten, damit man es
direkt richtig lernt, insbesondere bei solchen Fällen wo die korrekte
Lösung so einfach ist. Erst recht, wenn sogar der Compiler meckert:
1
test.c: In function ‘main’:
2
test.c:5:15: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
3
for (ix=0; ix< (sizeof(anArray)/sizeof(short)); ++ix)
In der konkreten Anwendung kann man sich dann immer noch überlegen ob
man's anders macht - immer noch besser, als das original falsch gelernte
zu un-lernen.
Einfach gesagt: Es ist fast scheiß egal, was du nutzt. Wichtig ist
erstmal, dass du die Grundlagen gut drauf hast und dich dann
weiterbildest und mit häufigen Fehlern beschäftigst.
So gut wie jedes Buch hat mehr oder weniger grobe Fehler drin, aber so
erkennst du sie dann selbst. Siehst ja hier, wie sich die Leute nicht
mal über Fehler einig sind.
Übung macht den Meister :-] schrieb:> kein int für den Schleifenzähler verwenden?
Wenn der Code exakt so aussieht, ist int ok. Aber in ähnlichem Code kann
so etwas schief gehen - da sollte man dann size_t verwenden. Ich
persönlich finde es am Einfachsten, wenn man sich die Regel angewöhnt
"Für Container und Arrays immer size_t nehmen" anstatt jedes einzelne
Mal nachzudenken "Reicht hier ein int?". Das provoziert nur Fehler,
insbesondere wenn man den Code später abändert. Es gibt ja auch
überhaupt keinen Grund, hier int zu nehmen - warum also darauf bestehen,
nur weil es in manchen Fällen geht?
Der Andere schrieb:> Im Kernighan Ritchie C gabs noch kein size_t
Ok, dann sind die beiden entschuldigt. Zum Glück gibts das aber
mittlerweile.
Dr. Sommer schrieb:> Der Andere schrieb:>> Im Kernighan Ritchie C gabs noch kein size_t> Ok, dann sind die beiden entschuldigt. Zum Glück gibts das aber> mittlerweile.
Ist aber falsch.
Mein Gott, ist das Forum grottenschlecht...
Voll mit knausrigen, halbgebildeten i-Tüpfelreitern
Hat irgendjemand hier mal mehr als ein Hello World geschrieben?
Ich finde das solche Openbooks schon okay sind, wer da Fehler sieht
braucht das Buch auch nicht mehr.
Das wichtigste ist ja die Grundlagenvermittlung für ein breites Publikum
(ausgenommen jene die ein besseres Buch schreiben möchten ;) ), also die
erstmal überhaupt die Programmiersprache kennenlernen möchten verstehen
nach einem besagten Fehlerhaften Artikel wahrscheinlich nichtmal wo denn
im aufgezeigten Fehler der Unterschied besteht.
Ich denke viele dieser "Fehler" stehen nichtmal im Vergleich zum
Kapitelkontext.
Bessere Lektüre gibt es immer.
Dr. Sommer schrieb:> 5.2 Der Datentyp »int« (Integer)> Der Datentyp int muss, gemäß ANSI C, mindestens eine Größe von zwei Byte> aufweisen. Mit diesen zwei Bytes lässt sich ein Zahlenraum von -32768> bis +32767 beschreiben>> Das Minimum ist -32767, nicht -32768, denn C unterstützt auch Systeme> die das Einerkomplement nutzen. Die allermeisten nutzen aber das> Zweierkomplement und können bis -32768.
Abgesehen davon ist auch die Größe eines Bytes in C nicht fix definiert,
sondern implementation-defined. Ein int darf auch ein Byte groß sein.
Und Reihenfolge der obigen "Herleitung" ist eigentlich genau umgekehrt:
Vorgegeben ist der Wertebereich, und daraus ergibt sich dann, wie groß
der Typ mindestens sein muss.
Rolf M. schrieb:> Abgesehen davon ist auch die Größe eines Bytes in C nicht fix definiert,
Genau. Es war wohl "Oktett" gemeint.
Philipp K. schrieb:> Ich finde das solche Openbooks schon okay sind, wer da Fehler> sieht> braucht das Buch auch nicht mehr.
Es geht nicht darum dass man Fehler sieht, es geht darum dass man es
falsch lernt, weil man sie als Anfänger eben nicht sieht. Daher sollte
man halt mal die paar Euro in ein gutes Buch investieren. Höhrere
Mathematik lernt man auch nicht mit eine paar Online-Tutorials.
Dr. Sommer schrieb:> Es geht nicht darum dass man Fehler sieht, es geht darum dass man es> falsch lernt,
Die Frage ist ob es die Zielgruppen an die das Buch gerichtet ist im
Gegensatz zu nen paar Oberschlaumeiern überhaupt interessiert.
Philipp K. schrieb:> Die Frage ist ob es die Zielgruppen an die das Buch gerichtet ist im> Gegensatz zu nen paar Oberschlaumeiern überhaupt interessiert.
Wenn der Code nicht funktioniert weil es falsch gelernt wurde, wird es
denjenigen interessieren. Hier - bei einem anderen Open Book - wird ein
Beispiel zitiert welches komplett falsch ist und so nie funktionieren
wird:
https://www.c-plusplus.net/forum/272350-10 . Ist das auch noch
oberschlau?
Wie oben schon gesagt wurde: Man muss nicht jedes Detail in so ein Buch
reinschreiben, aber das was drin steht, muss auch korrekt sein.
Einfach zu sagen, wenn Details falsch sind, ist das völlig egal, weil
das einen Anfänger eh nicht interessiert, halte ich für keinen
sinnvollen Weg.
Oder anders gesagt: Es kann kein Qualitätsmerkmal eine Lehrbuchs sein,
dass nur die Dinge falsch sind, bei denen des den Anfänger nicht
interessiert.
Dr. Sommer schrieb:> Es geht nicht darum dass man Fehler sieht, es geht darum dass man es> falsch lernt, weil man sie als Anfänger eben nicht sieht.
Man lernt es doch gar nicht "falsch". Man bezieht sich auf eine
bestimmte Implementierung. Anders geht es doch auch gar nicht. Was nützt
dir der Hinweis "int" kann 8, 16, 32, 64 oder sonst wie bittig sein?
Damit kannst du nicht programmieren lernen. Du brauchst EINEN Bezug. Das
ist im K&R (den ihr Schlauberger fälschlicherweise pauschal als "size_t"
gab's dort noch gar nicht betitelt habt) 1) auch nicht anders geregelt.
Er bezieht sich nämlich auf die Implementierung der 16-bit Ära, die
damals aktuell war. Folglich hat "int" einen Wertebereich von -32768 bis
+32767. Dies wird beim ersten Nennen von int erwähnt (bei mir S. 9)
natürlich mit dem Hinweis, dass int mit 32-bit genau so üblich sei
(damals im Workstation Bereich). Dennoch ist weiter hinten im Auszug
B.11 einer Tabelle aus limits.h
INT_MIN -32767
INT_MAX +32767
angegeben. Damals halt wegen Einerkomplement.
Damit nimmt das Buch klar Bezug zur Größe von int, so wie es die meisten
damals auch zu erwarten hatten, die das Buch kaufen. DOS-Ära! Und wer
bitte hatte schon eine VAX zu Hause stehen?
1) ohne die Ausgabe zu nennen !! Zweite Ausgabe ANSI C kannte size_t
bereits!
Rolf M. schrieb:> Man muss nicht jedes Detail in so ein Buch> reinschreiben, aber das was drin steht, muss auch korrekt sein.
So ein Anspruch SCHEITERT an der Wirklichkeit!
1. Ein fehlerfreies Buch gibt es nicht, gab es nie, wird es nie geben.
2. Ein Buch, dass Eierlegende Wollmilchsau spielt, d.h. sich nicht auf
eine sinnvolle Auswahl beschränkt (JA, dazu gehört auch im Jahre 2008
aufwärts das verdammte Einerkomplement in den Orkus zu werfen. Braucht
keiner mehr!), wird seinem Anspruch nicht gerecht. Der Anspruch ist
Anfängern beim Lernen zu helfen und nicht Enzyklopädie zu spielen. Das
überlassen wir den Juristen mit ihren Pamphleten. Die können sich dann
um Vokabeln kloppen.
Ihr habt vergessen, wie ihr einst in der Schule das Rechnen begonnen
habt.
3 : 2 = 1 Rest 1
War das exakte Mathematik?
Übung macht den Meister :-] schrieb:> Dr. Sommer schrieb:>> Es geht nicht darum dass man Fehler sieht, es geht darum dass man es>> falsch lernt, weil man sie als Anfänger eben nicht sieht.>> Man lernt es doch gar nicht "falsch". Man bezieht sich auf eine> bestimmte Implementierung.
Wenn das dann auch so dabei steht, wäre das auch noch ok. Aber das
bezieht sich doch ganz offensichtlich nicht auf eine bestimmte
Implementierung. Oder bei welcher konkreten Implementierung ist die
Größe von int mindestens (und nicht etwa exakt) zwei Bytes groß? Das
stimmt so weder für irgendeine gängige Implementation, noch für C
allgemein.
Übung macht den Meister :-] schrieb:> 1. Ein fehlerfreies Buch gibt es nicht, gab es nie, wird es nie geben.
Ja, genauso wie es keine absolut fehlerfreie Software geben kann. Und
nun? Soll man daraus etwa ableiten, dass Fehler egal sind?
> 2. Ein Buch, dass Eierlegende Wollmilchsau spielt, d.h. sich nicht auf> eine sinnvolle Auswahl beschränkt
Ich schreibe es gern ein drittes mal: Eine sinnvolle Auswahl ist völlig
ok, aber zur Vereinfachung Dinge zu schreiben, die falsch sind, ist in
einem Lehrbuch nicht angebracht.
Übung macht den Meister :-] schrieb:> Ist aber falsch.udok schrieb:> Mein Gott, ist das Forum grottenschlecht...> Voll mit knausrigen, halbgebildeten i-Tüpfelreitern> Hat irgendjemand hier mal mehr als ein Hello World geschrieben?
Wieder mal ein paar Dummschwätzer die nur Unruhe stiften aber absolut
nix substanzielles beitragen können.
Wahrscheinlich nie über C64-Basic hinausgekommen ;p
Oh mein Gott wenn man diesen ganzen Genöhle hier liest!
Es gibt nicht DAS perfekte Buch um C zu lernen, wird es auch nie geben,
speziell bei C oder C++, die Sprachen sind immer "im Flow" und
wachsweich spezifiziert. Nimm irgendein Buch, deine Wahl fiel auf das
Buch oben, arbeite das Buch durch und dann ein anderes und lerne aus den
Unterschieden und vor allem: schreibe selber Code bis zu vergasen und
lese anderen Code (Open Source sei dank), dann lernste am meisten. Wenn
du mal pause machst dann liest in entspr. Foren mit da stolpert man auch
auf das eine oder andere was man noch nicht kennt.
Der Andere schrieb:> Wieder mal ein paar Dummschwätzer die nur Unruhe stiften aber absolut> nix substanzielles beitragen können.
Ich weiß nicht wen du hier adressierst. Meine Aussage zu size_t stimmt
jedenfalls.
Ich habe das Buch nicht gelesen und will es auch nicht bewerten, aber
beim Überfliegen des Inhaltsverzeichnis' fand ich "12.6 Zeiger als
Funktionsparameter (call–by–reference)" etwas eigenwillig, da C gar kein
call by reference unterstützt; stattdessen werden Parameter immer per
call by value übergeben. Leider findet sich so eine missbräuchliche
Verwendung von standardisierter Terminologie in vielen C- und auch
Java-Büchern.
Übung macht den Meister :-] schrieb:> Und welche Formulierungen verwenden andere Druckwerke? Beispiele> gefällig?
Na, wer hat hier von wem abgeschrieben und Dinge für selbstverständlich
erklärt die gar nicht stimmen...
Ich versteh auch das Problem nicht. Wenn man einen Integer-Typ mit
Bereich -32767 bis 32767 haben will, nimmt man int_least16_t. Wenn man
-100000 bis 100000 haben will, nimmt man int_least32_t. Warum sich erst
kompliziert Gedanken machen ob ein int jetzt groß genug ist oder
vielleicht auf der Plattform ein short auch reicht? Einfach das
ausnutzen was der Standard garantiert und nichts kann einem was
kaputtmachen.
Übung macht den Meister :-] schrieb:> Das verwundert stark, bist doch du derjenige, der das Problem entdeckt> hat.
Ich bin nicht derjenige der sagt "aber auf Platform XY geht es ja doch"
oder "ich muss unpassende Integer-Typen nutzen und das irgendwie
verargumentieren"... Wenn man für alles und jedes "int" nehmen will,
nimmt man Java. Eine der Stärken von C und C++ ist es, dass man viele
verschiedene Typen zur Auswahl hat und man sich den Geeigneten nehmen
kann.
Übung macht den Meister :-] schrieb:> Ihr seht, der "Schuldige" findet sich in bester Gemeinschaft wieder.
Einige davon enthalten keine falsche Aussage.
Ok fehlerfrei ist das von mir empfohlene Netz-Buch nicht. Mir hat es am
Anfang aber gereicht und es war umsonst.
Später hat man sich andere Literatur besorgt und dort auch Fehler
gefunden.
Zum ersten probieren und ein Verständnis zu bekommen bis Pointer, war es
mir als Student ausreichend genug und umsonst günstig genug und immer
erreichbar,um erste Spielereien zu machen.
Und genau das ist es was meines der Herr gesucht hat einen ersten
Einstieg und Überblick nicht ein perfektes Werk für alle Lebenslagen.
Wenn jemand uC lernen möchte dann möchte man erste Erfolge sehen da
reicht das Buch und Radigs Seite und diese Seite um erste Erfolge zu
sehen nen Display anzusteuern ein paar Leds blinken zu lassen und spass
am lernen zu bekommen. Ihrgend wann braucht man mehr, dann gibt man auch
gerne 100-200€ für nen Buch wie Tietze und Schenk aus.
Am Anfang reicht mein Vorschlag, da wird man nur verwirrt durch die
ganzen Kleinigkeiten die man noch beachten kann.
Schneller Erfolg motiviert und macht Lust auf mehr es macht da kein Sinn
die Leute zu verwirren, das wird hier im Forum leider viel zu oft getan
und Leute die anfangen wollen mit basteln ohne Vorwissen verarscht oder
runtergemacht das Hobby soll Spaß machen nicht frustrieren.
Bitte um Vorschläge für bessere Literatur.
Das geht hier in diesem Forum leider oft unter da wird Stundenlang sich
an Kleinigkeiten aufgegeilt( kein angriff auf Dr. Sommer ).
Fehler solte man melden, dann werden die mit Sicherheit auch ausgemerzt.
Gibt halt nie immer das optimale Buch, selbst der Bronstein ist nicht
allwissend aber mit 30€ nahe dran und perfekt fürs Studium. Da muss man
halt auch mal da mit leben, dass das Papier so dünn ist das man
durchschauen kann und, das das Buch nach den Mathe Prüfungen
auseinanderfällt.
Rechtschreibfehler dürfen gefunden und behalten werden.
Wünsche allen ein schönen erfolgreichen Freitag und nen ruhiges
Wochenende und hoffe dass das Forum ein wenig gesitteter wird.
Dr. Sommer schrieb:> Ich versteh auch das Problem nicht. Wenn man einen Integer-Typ mit> Bereich -32767 bis 32767 haben will, nimmt man int_least16_t. Wenn man> -100000 bis 100000 haben will, nimmt man int_least32_t.
Richtig.
Aber in welchem Lehrbuch wird das denn so vermittelt?
Gerade mit dem "least".
Meist wird doch das int32_t ohne Not benutzt.
Dirk B. schrieb:> Aber in welchem Lehrbuch wird das denn so vermittelt? Gerade mit dem> "least".
Keine Ahnung. Hier ist zu sehen dass der Austausch mit Experten sehr
wichtig ist. Ich hab z.B. viele Anregungen im ##C++ Channel im FreeNode
IRC bekommen... natürlich sollte man die Aussagen dann im Standard
nachprüfen, konkrete Punkte kann man damit durchaus beantworten, auch
wenn er zum reinen Durcharbeiten ungeeignet ist.
Die Wolfbücher sind Teil einer spammenden Unkultur. Das gibt es in
vielen Büchern von Journalisten, und die haben nur den Anfang gemacht.
Gewissermaßen genau das andere Ende von Buch mit nur Befehlsliste a la:
friss und.. mach was draus.
Ubuntu zeigt ganz deutlich, dass es etwas besser schmeckt mit ein wenig
Geld (oder bei ähnliche Reizen, wie Lehrer in Schule übertrumpfen
o.ä.).
Bei C ist das so, dass die Abstraktionen zuerstmal sacken müssen. Dieses
optimierte "Denken" braucht man dann auch z.B. wenn man gute Programme
mit endlichen Automaten (grep oder zip z.B.), Audiofilter,
Betriebssysteme.. usw. usw. schreiben möchte.
Das braucht alles Motivation und Zeit .. (s.o.).
Peter M. schrieb:> Ich würde gerne genauer wissen, wieso das Buch grottenschlecht
Also ich als Anfänger fand das Buch sehr gut. Das auf dein Posting
folgende gemäkel versteh ich nicht.
Wieso z.B. ist ein Lehrbuch schlecht wenn es nicht alle Typen in einem
Kapitel aufführt und
Dr. Sommer schrieb:> Das Minimum ist -32767, nicht -32768,
Ja und? Das ist ein Lehrbuch und kein Referenzwerk.
Dr. Sommer schrieb:> Ganz schlechter Stil, dafür nimmt man typedef
Ein Beispiel mit etwas zu erklären was erst später behandelt wird. Das
ist ganz schlechter Stil. Selbst wenn es schon behandelt wurde ist es
imho besser die einfachst mögliche Form zu nehmen.
Dr. Sommer schrieb:> "Das Verhalten ist in diesem Fall undefiniert."> Es ist implementation-defined,
Und wo ist der Unterschied in der Praxis? Warum muss jemand der C Syntax
lernt das wissen? Ist es nicht information overload?
X4U schrieb:> Ja und? Das ist ein Lehrbuch und kein Referenzwerk.
Ok, wenn du der Ansicht bist dass Lehrbücher fehlerhaft sein dürfen.
X4U schrieb:> Selbst wenn es schon behandelt wurde ist es> imho besser die einfachst mögliche Form zu nehmen.
Was an typedef ist komplizierter? Es ist sogar einfacher, weil es später
weniger Probleme verursacht.
X4U schrieb:> Ein Beispiel mit etwas zu erklären was erst später behandelt wird.
Dann kann man immer noch darauf verweisen. In einem Beispiel etwas
falsch zu machen dass sehr oft falsch gemacht wird ist offensichtlich
ziemlich mies.
X4U schrieb:> Und wo ist der Unterschied in der Praxis?
Auf Implementation-Defined Behaviour kann man sich in gewissen Grenzen
verlassen, Undefined Behaviour nicht. IMO sollte man keines von beiden
annehmen.
X4U schrieb:> Warum muss jemand der C Syntax> lernt das wissen? Ist es nicht information overload?
Wer unbedingt C lernen will, muss sich auf eine Flut an komplizierten
Informationen einstellen. Wenn man einfach nur programmieren lernen
will, sollte man lieber Python o.ä. nehmen.
Es ist erwiesenermaßen didaktisch äußerst ungeschickt, zu zeigen wie es
nicht geht, selbst wenn dran steht dass es so falsch ist - erst recht
wenn es kommentarlos falsch ist und man sich das "später" richtig
angucken soll. Denn die Leute merken sich genau das und wiederholen es
so. Du sagst ja auch deinem Kind nicht "Du sollst nicht fluchen,
Idiot!".
Karl schrieb im Beitrag #5310102:
> Meistens ist nichts brauchbares dabei, wie in> deinen Beispielen.
Nur kein Neid!
Hier noch ein kleines Beispiel warum #define für Typen schlecht ist:
Angenommen wir erfinden gerade das Windows-API neu, und definieren uns
einen Typ "HANDLE". Dieser wird von diversen API-Funktionen genutzt und
zurückgegeben. Der Nutzer kann mit diesem Typ nichts anfangen, sondern
ihn nur übergeben. Das ist ein ganz typisches Vorgehen in C. Wir fangen
an und definieren ihn einfach als Alias für "uint8_t":
1
#define HANDLE uint8_t
Der Nutzer kann dann so etwas schreiben:
1
HANDLEa,b;
2
a=CreateFile(...);
3
b=CreateFile(...);
4
...
5
CloseHandle(a);
6
CloseHandle(b);
Jetzt fällt uns auf dass ein Integer doch nicht so schlau war, und wir
ändern das auf "void*":
1
#define HANDLE void*
Jetzt ist diese Code plötzlich fehlerhaft, obwohl der Nutzer keinerlei
Annahmen über die Interna von HANDLE gemacht hat:
1
HANDLEa,b;
Weil "b" als "void" statt "void*" definiert wird! Dies gibt einen
Compiler-Fehler. Der Code müsste also angepasst werden:
1
HANDLEa,*b;
Das ist jetzt völlig verwirrend für den Leser. Wenn man das HANDLE dann
nochmals umdefiniert gibts wieder ein Problem.
Hätten wir einfach ein Typdef genommen wäre alles in Butter:
1
typedefvoid*HANDLE;
Dann ist
1
HANDLEa,b;
immer noch korrekt. Es gibt noch weitere Beispiele, z.B. bei Arrays. Der
Grund für die Probleme liegt in der verdrehten C-Syntax sowie darin,
dass Makros nur dumme Textersetzung machen.
Jetzt könnte man natürlich sagen, dass für einfache Fälle - wie Integer
- das #define ausreicht. Das ist zwar korrekt, aber warum jedes Mal
überlegen "Brauche ich ein typedef oder bin ich mir absolut sicher
niemals den Typ auf einen Pointer zu ändern und kann somit #define
nutzen" wenn ich mir auch einfach merken kann "immer typedef nutzen".
Bei #define spart man nichtmal ein einziges Zeichen Code.
Wenn man jetzt im Buch sowas wie "#define BYTE unsigned char" liest,
merkt man sich das, insbesondere wenn man das folgende Kapitel über
"typedef" nicht liest. Da dieser Fehler weit verbreitet ist sollten die
Autoren Wert darauf legen, es gleich richtig zu zeigen...
Dr. Sommer schrieb:> X4U schrieb:>> Ja und? Das ist ein Lehrbuch und kein Referenzwerk.> Ok, wenn du der Ansicht bist dass Lehrbücher fehlerhaft sein dürfen.
Meinst du wirklich DEINE Ansicht darüber würde etwas an der Tatsache
ändern, dass Lehrbücher nun mal Fehler enthalten?
Fehler werden üblicherweise in der nachfolgenden Auflage (falls es eine
gibt) korrigiert, so sie bekannt sind und als solche auch erachtet
werden. Meistens werden dann auch gleich Kapitel ergänzt und dabei
wieder neue Fehler eingebracht. Fehlerfrei gibt es also nicht!
Aber mal was Grundsätzliches,
immerhin ist die Online-Ausgabe dieses Druckwerks umsonst, d.h. sie
kostet 0 Euro. Du formulierst nun einen Anspruch daran ohne dafür
bezahlt zu haben und das Buch wird deiner Meinung nach deinem Anspruch
nicht gerecht. Interessant dabei ist, wann immer man einen ähnlichen
Anspruch z.B. an Open Source SW stellt (z.B. gute Doku, intuitive
Bedienbarkeit, Fehlerfreiheit o.ä.), reagieren gerade Leute wie du
(damit meine ich Leute die selber Software schreiben) angesäuert und
kontern, man hätte doch schließlich nix bezahlt dafür, also hätte man
die Füße stillzuhalten. Hier jedoch ereifern sich die "Genossen
Programmierer" wie im erwähnten Thread 1) anscheinend über 31 WebSeiten
!! lang (hab's nicht gelesen, wozu auch) mit dem Niedervoten dieses
Lehrbuchs. Schon interessant, wie hier von manchen mal wieder mit
zweierlei Maß gemessen wird.
1) https://www.c-plusplus.net/forum/272350
Darf man demnächst auch "Warnthreads" vor bestimmten halbgaren Open
Source Programmen erstellen? (ohne dass einen der Shitstorm ereilt)
Nein, ich bin kein "OS Hasser". Wollte nur mal einen Vergleich ziehen.
Übung macht den Meister :-] schrieb:> Meinst du wirklich DEINE Ansicht darüber würde etwas an der Tatsache> ändern, dass Lehrbücher nun mal Fehler enthalten?
Darum ging es nicht.
Übung macht den Meister :-] schrieb:> Fehler werden üblicherweise in der nachfolgenden Auflage (falls es eine> gibt) korrigiert, so sie bekannt sind und als solche auch erachtet> werden.
Anscheinend wissen hier Autor und Verlag sehr wohl um die Fehler, tun
aber nix.
Übung macht den Meister :-] schrieb:> Du formulierst nun einen Anspruch daran ohne dafür> bezahlt zu haben und das Buch wird deiner Meinung nach deinem Anspruch> nicht gerecht.
Falsch. Ich sage, dass man das Buch nicht zum Lernen nehmen sollte, und
lieber Geld in ein richtiges investieren soll:
Dr. Sommer schrieb:> Daher sollte> man halt mal die paar Euro in ein gutes Buch investieren. Höhrere> Mathematik lernt man auch nicht mit eine paar Online-Tutorials.Übung macht den Meister :-] schrieb:> Schon interessant, wie hier von manchen mal wieder mit> zweierlei Maß gemessen wird.
Bei Open Source Software besteht immerhin nicht das Risiko, eine
Generation von Programmierern mit gefährlichem Halbwissen
heranzuzüchten.
Übung macht den Meister :-] schrieb:> Darf man demnächst auch "Warnthreads" vor bestimmten halbgaren Open> Source Programmen erstellen?
Gibts doch schon jede Menge.
Gerade bei C-Büchern gibts eine riesige Auswahl, und da soll man sich
mit einem begnügen wo man nach ein paar Minuten schon Fehler findet? So
eine Auswahl hat man bei Software oft nicht.
Dr. Sommer schrieb:> Gerade bei C-Büchern gibts eine riesige Auswahl, und da soll man sich> mit einem begnügen wo man nach ein paar Minuten schon Fehler findet?
Wer schreibt denn sowas? Ich jedenfalls nicht.
Kennst du den Satz: "Aus Fehlern wird man klug." Der Lerneifer beim
Programmieren wird selber viel mehr Programmierfehler hervorbringen. Da
gehen die paar Ungenauigkeiten aus dem Buch im Rauschen unter. Außerdem
gehst du von der falschen Denke aus, dass EIN Buch mit ein paar Fehlern
darin zwangsläufig zu lebenslangen nicht reflektierten, unkorrigierten
eigenem Fehlverhalten führt. Das ist Nonsens.
Lesen allein genügt sowieso nicht, das zeigen die Irrungen und Wirrungen
des Buchhändlers aus Würselen. Der soll übrigens jede freie Minute
gelesen haben, dass die Schwarte kracht.
Übung macht den Meister :-] schrieb:> Da> gehen die paar Ungenauigkeiten aus dem Buch im Rauschen unter.
Na, und da beschweren sich noch Leute C sei schwer zu lernen.
Übung macht den Meister :-] schrieb:> Außerdem> gehst du von der falschen Denke aus, dass EIN Buch mit ein paar Fehlern> darin zwangsläufig zu lebenslangen nicht reflektierten, unkorrigierten> eigenem Fehlverhalten führt. Das ist Nonsens.
Guck dir mal den Code von W.S. an. Der hat's bis heut nicht gelernt.
Oder der Linux Kernel, dessen Code funktioniert nur mit dem GCC, mit
einer bestimmten alten Sprachversion, und nur mit -fno-strict-aliasing
aktiviert, d.h. wenn eine bestimmte Art fehlerhaften Codes erlaubt ist.
Das verhindert eine Klasse von Optimierungen. Mit anderen Worten: Linux
ist unnötig langsam, weil die Linux-Kernel-Entwickler keine Lust haben,
korrekten Code zu schreiben.
Dr. Sommer schrieb:> Mit anderen Worten: Linux> ist unnötig langsam, weil die Linux-Kernel-Entwickler keine Lust haben,> korrekten Code zu schreiben.
in welcher Sprache mag dann Windows erst geschrieben sein?
Walter K. schrieb:> in welcher Sprache mag dann Windows erst geschrieben sein?
Der Kernel natürlich auch in C. Wenn die den Code derart geheim halten
muss er furchtbar sein :)
Dr. Sommer schrieb:> Oder der Linux Kernel, dessen Code funktioniert nur mit dem GCC, mit> einer bestimmten alten Sprachversion, und nur mit -fno-strict-aliasing> aktiviert, d.h. wenn eine bestimmte Art fehlerhaften Codes erlaubt ist.
Der Linux-kernel ist schon ein paar Jahre älter als die Strict-Aliasing-
Rule. Die fraglichen Teile des Linux-Kernels waren nicht von Anfang an
fehlerhaft, sondern wurden es erst mit der Einführung von C99, das in
diesem Punkt nicht abwärtskompatibel zur früheren C-Versionen ist.
Ich habe es aber auch kaum erlebt, dass realer Programmcode durch
-fno-strict-aliasing signifikant langsamer geworden wäre.
Na ja, wenn jemand die Programmiersprache lernen soll, müsste derjenige
doch erstmal als allererstes lernen, die Warnungslevel vom Compiler
hochzudrehen. Dann isses doch Hupe, welches Buch derjenige nimmt. Das
ist aber auch der härteste Weg, den man gehen kann, um ne
Programmiersprache zu lernen.
Der Compiler halt das erste und das letzte Werkzeug vom Programmierer,
dass Ding muss man handwerklich beherrschen können. Vielleicht ist da
portabelst möglicher Code für ein Grundlagenbuch die beste Empfehlung,
damit man das so breitbandig wie möglich durch die Compiler jagen kann.
Aber halt mit der Empfehlung "Warnungslevel rauf", damit man die
Fehler/Warnungen zu beheben lernt.
Ich hatte damals mit "C für Linux in 21 Tagen" angefangen (ja, lacht
nur...) und das ging auch damit, da man erstmal überhaupt was sieht. K&R
ist aber so schlecht nicht für Einsteiger.
Dass man nach so 'nem Grundlagenbuch eigentlich noch gar nix kann, was
die ganzen anderen Aspekte der Softwareentwicklung betrifft (Testen,
Requirements, Doku, Refactoring, Zeitrahmen einhalten, ...), ist doch
ohnehin klar.
Yalu X. schrieb:> sondern wurden es erst mit der Einführung von C99, das in> diesem Punkt nicht abwärtskompatibel zur früheren C-Versionen ist.
Ach tatsächlich, ok dann ist Linux entschuldigt...
Dr. Sommer schrieb:> Beispiel zitiert welches komplett falsch ist und so nie funktionieren> wird:> https://www.c-plusplus.net/forum/272350-10 . Ist das auch noch> oberschlau?
Naja das Geheimnis des Beispiels ist das es funktioniert..
Siehe letzten Beitrag hier:
https://www.c-plusplus.net/forum/271822-full
Ich finde aber das das Beispiel ganz gut die Vielfältigkeit der
Pointermöglichkeiten aufzeigt. Für mich als Berufsfremder okay und gut
veranschaulicht.
Yalu X. schrieb:> Der Linux-kernel ist schon ein paar Jahre älter als die Strict-Aliasing-> Rule. Die fraglichen Teile des Linux-Kernels waren nicht von Anfang an> fehlerhaft, sondern wurden es erst mit der Einführung von C99, das in> diesem Punkt nicht abwärtskompatibel zur früheren C-Versionen ist.
Wie sicher bist du dir da? Ich habe hier ein pdf, das sich ansi/iso
9899-1990 nennt. Darin steht in im Kapitel 6.3 "Expressions" folgender
Absatz:
1
An object shall have its stored value accessed only by an lvalue that has one of the following types:*
2
- the declared type of the object,
3
- a qualified version of the declared type of the object.
4
- a type that is the signed or unsigned type corresponding to the declared type of the object,
5
- a type that is the signed or unsigned type corresponding to a qualified version of the declared type of the object.
6
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a aggregate or contained union), or
7
- a character type.
8
9
* The Intent of the list is to specify those circumstances in which an object may or may not be aliased.
Im c11 Draft (n1579) steht folgendes in Kapitel 6.5 "Expressions":
1
7 An object shall have its stored value accessed only by an lvalue expression that has one of
2
the following types:*
3
— a type compatible with the effective type of the object,
4
— a qualified version of a type compatible with the effective type of the object,
5
— a type that is the signed or unsigned type corresponding to the effective type of the
6
object,
7
— a type that is the signed or unsigned type corresponding to a qualified version of the
8
effective type of the object,
9
— an aggregate or union type that includes one of the aforementioned types among its
10
members (including, recursively, a member of a subaggregate or contained union), or
11
— a character type.
12
13
* The intent of this list is to specify those circumstances in which an object may or may not be aliased.
Ich frage mich übrigens gerade, ob es heutzutage für einen Anfänger noch
Sinn macht, mit einem reinen C Buch anzufangen. Sollte man nicht gleich
ein C++ Buch lesen? Wenn man sich dann später auf C beschränken will,
ignoriert man eben den OOP Kram mit Klassen und die C++ Bibliotheken
usw. Die OOP Grundidee ist heute ja eh Allgemeinwissen, so dass man sich
dadurch nicht so viel mehr unnötigen Lernaufwand aufbürded, und die
Kapitel des Buches die C++ Bibliotheken beschreiben kann man ja
(zunächst) ignorieren.
Ich habe C vor langer Zeit mit irgendeinem billigen und eher schlechten
C-Buch gelernt. Jedenfalls habe ich den Eindruck, dass Bücher wie der
C++ Primer von Lippman schon ganz gut erklären. Ein paar reine C-Sachen
wie Datentyp struct oder C specifischen Input/Output mag fehlen, aber
gut das kann man in Online-Quellen nachlesen.
Philipp K. schrieb:> Naja das Geheimnis des Beispiels ist das es funktioniert..
Hm. Also ich sehe im C-Standard keinerlei Garantie, dass der von strtok
zurückgegebene Zeiger auf einen statischen Speicher zeigt. Und selbst
wenn, wäre es doch ein extrem schlechter Stil. Valgrind meckert bei dem
Programm auch.
Stefan schrieb:> Sollte man nicht gleich> ein C++ Buch lesen?
Meiner Meinung nach ja; wenn man C++ kann ist es relativ leicht auf C
umzusteigen. Natürlich wird man sich dann ärgern dass C so limitiert ist
und lieber so viel wie möglich in C++ machen.
Dr. Sommer schrieb:> Mit anderen Worten: Linux> ist unnötig langsam, weil die Linux-Kernel-Entwickler keine Lust haben,> korrekten Code zu schreiben.
Die Implementierung von strict aliasing war zumindest umstritten:
https://stackoverflow.com/questions/2958633/gcc-strict-aliasing-and-horror-stories
Oder mit Linus' Worten: I tried to get a sane way a few years ago, and
the gcc developers really didn't care about the real world in this area.
... I'm not going to bother to fight it.
Mikro 7. schrieb:> Oder mit Linus' Worten
Was der so von sich gibt muss man nicht so ernst nehmen... Ist bei dem
Anteil an Beschimpfungen auch besser für die geistige Gesundheit.
Übung macht den Meister :-] schrieb:> Außerdem gehst du von der falschen Denke aus, dass EIN Buch mit ein paar> Fehlern darin zwangsläufig zu lebenslangen nicht reflektierten,> unkorrigierten eigenem Fehlverhalten führt.
Vielleicht nicht zwangsläufig, aber die Erfahrung zeigt, dass es doch
sehr oft so ist. Ich habe schon öfters erlebt, dass Leute, die schon
seit vielen Jahren in C programmieren, plötzlich auf ein Problem stoßen,
weil sie mal was gelernt haben, was so aber falsch ist.
Warum sollte man auch ohne konkreten Grund alles infrage stellen, was
man je gelernt hat? Man geht ja nicht a priori davon aus, dass das alles
falsch ist. Umso wichtiger ist, dass bei Lehrbüchern darauf geachtet
wird, das keine vermeidbaren Fehler drin sind.
Philipp K. schrieb:> Dr. Sommer schrieb:>> Beispiel zitiert welches komplett falsch ist und so nie funktionieren>> wird:>> https://www.c-plusplus.net/forum/272350-10 . Ist das auch noch>> oberschlau?>> Naja das Geheimnis des Beispiels ist das es funktioniert..
So ein einfacher Fall wird meistens funktionieren. In größeren
Programmen wird das aber schnell zum Fehler führen, und wer das bei so
einem einfachen Programm nicht richtig gelernt hat, erlebt spätestens
dann das böse Erwachen.
> Ich finde aber das das Beispiel ganz gut die Vielfältigkeit der> Pointermöglichkeiten aufzeigt. Für mich als Berufsfremder okay und gut> veranschaulicht.
Naja, als Berufsfremder wird man es vielleicht auch anschaulich finden,
wenn jemand mit einem Hammer eine Schraube in die Wand klopft, und es
mag auch funktionieren. Aber es ist eben trotzdem blödsinnig.
Dr. Sommer schrieb:> Philipp K. schrieb:>> Naja das Geheimnis des Beispiels ist das es funktioniert..> Hm. Also ich sehe im C-Standard keinerlei Garantie, dass der von strtok> zurückgegebene Zeiger auf einen statischen Speicher zeigt.
Der zurückgegebene Zeiger zeigt auf den Speicher, den man ihm übergeben
hat. Und der ist in diesem Fall nicht statisch.
Rolf M. schrieb:> Der zurückgegebene Zeiger zeigt auf den Speicher, den man ihm übergeben> hat. Und der ist in diesem Fall nicht statisch.
In der Linux man-Page heißt es:
"* The strtok() function uses a static buffer while parsing, so it's not
thread safe."
Daraus zu folgern dass man das als statischen Puffer missbrauchen kann
ist aber schon kriminell. Die Größe ist ja auch fix. Und im C-Standard
steht's ja auch nicht.
Eine der Fallen von C ist ja, dass viele Dinge den Anschein haben zu
funktionieren, aber falsch sind und bei veränderten Bedingungen
(Compiler/Version/Plattform) schief gehen. Das Argument "Funktioniert
doch" zählt hier überhaupt nicht...
Rolf M. schrieb:> Naja, als Berufsfremder wird man es vielleicht auch anschaulich finden,> wenn jemand mit einem Hammer eine Schraube in die Wand klopft, und es> mag auch funktionieren. Aber es ist eben trotzdem blödsinnig.
Ganz genau!
Dr. Sommer schrieb:> In der Linux man-Page heißt es:> "* The strtok() function uses a static buffer while parsing, so it's not> thread safe."> Daraus zu folgern dass man das als statischen Puffer missbrauchen kann> ist aber schon kriminell.
Es nutzt den "static buffer" nicht für den eigentlichen Text, sondern
nur für den Zeiger auf den letzten Delimeter (bzw. allegemeiner für
interne Verwaltungsdaten), um zu wissen, wo beim nächsten Aufruf
weitergeparst werden muss. strtok() arbeitet ansonsten direkt auf dem
Speicher, den man ihm mit dem ersten Argument übergeben hat.
Rolf M. schrieb:> Philipp K. schrieb:>> Dr. Sommer schrieb:>>> Beispiel zitiert welches komplett falsch ist und so nie funktionieren>>> wird:>>> https://www.c-plusplus.net/forum/272350-10 . Ist das auch noch>>> oberschlau?>>>> Naja das Geheimnis des Beispiels ist das es funktioniert..>> So ein einfacher Fall wird meistens funktionieren. In größeren> Programmen wird das aber schnell zum Fehler führen, und wer das bei so> einem einfachen Programm nicht richtig gelernt hat, erlebt spätestens> dann das böse Erwachen.
Zitat: Beispiel zitiert welches komplett falsch ist und so nie
funktionieren wird
Meine meinung, nicht besser als das Beispiel weil diese Aussage nicht so
genau wie das Beispiel zutrifft!
Ich habe das Problem dabei aber schon sofort verstanden, auch wenn ich
noch nie was über Pointer gelesen habe.
Philipp K. schrieb:> Ich habe das Problem dabei aber schon sofort verstanden, auch wenn ich> noch nie was über Pointer gelesen habe.
Das hat mit Pointern auch nix zu tun, sondern mit dem Scope lokaler
Variablen.
Dr. Sommer schrieb:> Das hat mit Pointern auch nix zu tun, sondern mit dem Scope lokaler> Variablen.
Dann ist das Beispiel aber auch im Schreibstil verkehrt, soweit ich es
kenne.
Denn eine Funktion direkt zurückzugeben macht man sowieso nicht..
jedenfalls kenne ich das nur so und dann würde das Beispiel nicht mehr
funktionieren?
Philipp K. schrieb:> Denn eine Funktion direkt zurückzugeben macht man sowieso nicht..
Du meinst man soll kein "return irgendeineFunktion (...);" machen? Das
ist überhaupt kein Problem und sogar sinnvoll, weil es u.U. gewisse
Optimierungen wie tail-recursion ermöglicht bzw. einen Sprung statt
Aufruf. Man kann den Rückgabewert in eine Variable speichern und den
zurückgeben, aber was hätte das für einen Vorteil?
Philipp K. schrieb:> dann würde das Beispiel nicht mehr> funktionieren?
Das Beispiel funktioniert vermutlich schon nicht mehr wenn man in der
main, nach Zeile 18, irgendwas anderes einfügt, wie z.B. einen Aufruf an
eine andere Funktion. Dass es auf einer bestimmten Plattform den
Anschein hat zu funktionieren ist purer Zufall, es könnte auch irgendwas
anderes machen.
Ich habs jetzt mal ausprobiert. Rolf Magnus hatte recht, strtok gibt
auch unter Linux einen Zeiger auf den Eingabepuffer zurück. Ändert man
das Beispiel so (die "eingabe"-Funktion bleibt gleich!):
1
/* ptr13.c */
2
#include<stdio.h>
3
#include<stdlib.h>
4
#include<string.h>
5
#define MAX 255
6
7
char*eingabe(char*str){
8
charinput[MAX];
9
10
printf("Bitte \"%s\" eingeben: ",str);
11
fgets(input,MAX,stdin);
12
returnstrtok(input,"\n");
13
}
14
15
intmain(void){
16
char*ptr1,*ptr2;
17
18
ptr1=eingabe("Vorname");
19
ptr2=eingabe("Nachname");
20
printf("Hallo %s %s\n",ptr1,ptr2);
21
printf("%s, interssanter Nachname\n",ptr2);
22
returnEXIT_SUCCESS;
23
}
Sieht es so aus:
1
$ ./a.out
2
Bitte "Vorname" eingeben: Hans
3
Bitte "Nachname" eingeben: Meier
4
Hallo Meier Meier
5
Meier, interssanter Nachname
Das ist auf jeden Fall verkehrt, und der Fehler liegt in der
"eingabe"-Funktion, er tritt nur nicht unter jedem Umstand zu tage. Eine
Schraube mit dem Hammer einzuhämmern mag vielleicht manchmal
funktionieren, aber wenn man ein Bild dranhängt klappt das nicht mehr so
gut.
Ein weiteres Problem ist übrigens, dass das "str"-Argument an "eingabe"
nicht "const" ist.
Rolf M. schrieb im Beitrag #5311079:
> Kann es nicht, da strtok() den übergebenen String modifiziert.
Achja. In C++ darf man String-Literale nicht einfach überschreiben, hab
grad nich im Kopf wie das bei C ist...
Da hatte ich einen gedanklichen Fehler, deshalb hatte ich das Posting
wieder gelöscht. str ist ja nicht der String, der an strtok() geht,
sondern er wird nur per printf() ausgegeben. Daher sollte das
tatsächlich const sein.
Monokollonialer Antikörper mit Senf schrieb:> Nur aus Interesse, wie schneidet dieses Büchlein im Expertenstreit ab?> (ISBN: 3934358039 / 3-934358-03-9)
LOL.
Wenn ich negativen (sachlich begründeten) Kritiken auf Amazon lese:
MegaLOL.
Monokollonialer Antikörper mit Senf schrieb:> Nur aus Interesse, wie schneidet dieses Büchlein im Expertenstreit ab?> (ISBN: 3934358039 / 3-934358-03-9)>> Ebay-Artikel Nr. 232407127909
Merke: Vorsichtig sein, wenn dir ein C/C++ über den weg läuft.
Man weiß nie, ob die andere Person zu Faul ist zwischen C und C++ zu
unterscheiden oder, ob sie nicht weiß, dass es sich um zwei
unterschiedliche Sprachen handelt.
Karl schrieb:> Monokollonialer Antikörper mit Senf schrieb:>>> Nur aus Interesse, wie schneidet dieses Büchlein im Expertenstreit ab?>> (ISBN: 3934358039 / 3-934358-03-9)>> LOL.>>> Wenn ich negativen (sachlich begründeten) Kritiken auf Amazon lese:> MegaLOL.
Moment mal bitte. Wenn ich die Kritiken richtig interpretiere, hat KEIN
EINZELNER Rezensent inhaltliche Probleme oder sachlich begründete Kritik
am Inhalt a la Dr. Sommer am Originalbuch. Dir Kritik lautet einhellig
"das ist kein Buch für Nafänger und setzt mathematische Kenntnisse
voraus, anstatt Glitzibunti Olala Beispiele zu zeigen."
Wenn dem so ist, scheint es mir wenn überhaupt ein nicht gut
positioniertes Buch zu sein, aber bei weitem nicht ein schlechtes Buch.
Wäre also wenn es denn so ist durchaus ein Kaufkandidat für Jemanden,
der sich für Tiefe anstatt Jumpstart interessiert.
mh schrieb:> Merke: Vorsichtig sein, wenn dir ein C/C++ über den weg läuft.
Genau, das ist wie zu sagen "Ich kenn mich mit Java/Javascript aus" oder
"Ölbohren/Ölgemälde" :)
Adapter schrieb:> Moment mal bitte. Wenn ich die Kritiken richtig interpretiere, hat KEIN> EINZELNER Rezensent inhaltliche Probleme oder sachlich begründete Kritik> am Inhalt a la Dr. Sommer am Originalbuch.
Aber an dem anderen Galileo Buch. Ist jetzt die Frage ob da eine
Kausalität bestehen könnte.
Dr. Sommer schrieb:> mh schrieb:>> Merke: Vorsichtig sein, wenn dir ein C/C++ über den weg läuft.> Genau, das ist wie zu sagen "Ich kenn mich mit Java/Javascript aus" oder> "Ölbohren/Ölgemälde" :)>> Adapter schrieb:>> Moment mal bitte. Wenn ich die Kritiken richtig interpretiere, hat KEIN>> EINZELNER Rezensent inhaltliche Probleme oder sachlich begründete Kritik>> am Inhalt a la Dr. Sommer am Originalbuch.> Aber an dem anderen Galileo Buch. Ist jetzt die Frage ob da eine> Kausalität bestehen könnte.
Hä? Da wird also ein Buch in Sippenhaft genommen für ein schlechtes Buch
aus demselben Verlag? Was soll denn das? Ist das Buch nun schlecht, weil
es ein schlecht geschriebenes oder inhaltlich schlechtes Buch ist, oder
weil es zufällig im selben Verlag erschienen ist wie ein Anderes,
inhaltlich schlechtes Buch? Was ist das denn für eine Logik? Oder habe
ich da etwas falsch verstanden?
mh schrieb:> Yalu X. schrieb:>> Der Linux-kernel ist schon ein paar Jahre älter als die Strict-Aliasing->> Rule. Die fraglichen Teile des Linux-Kernels waren nicht von Anfang an>> fehlerhaft, sondern wurden es erst mit der Einführung von C99, das in>> diesem Punkt nicht abwärtskompatibel zur früheren C-Versionen ist.>> Wie sicher bist du dir da?
Jetzt nach deinem Beitrag überhaupt nicht mehr ;-)
Ich bin da wohl einem Gerücht aufgesessen und danke dir für die
Richtigstellung.
Die Strict-Aliasing-Rule gab es tatsächlich schon in C90, worauf bspw.
auch hier hingewiesen wird:
https://kristerw.blogspot.de/2017/07/strict-aliasing-in-c90-vs-c99-and-how.html
Der Autor zitiert dabei dieselben Ausschnitte aus den Normungsdokumenten
wie du.
Damit hat auch Dr. Sommer recht mit seiner Aussage, dass der
Linux-Kernel
fehlerhaften Code enthält.
Es stellt sich natürlich die Frage, ab elchem Zeitpunkt von den Linux-
Entwicklern erwartet werden konnte, sich des Problems bewusst zu sein,
und wieviel fehlerhafter Code bis dahin schon geschrieben war.
Yalu X. schrieb:> Damit hat auch Dr. Sommer recht mit seiner Aussage, dass der> Linux-Kernel> fehlerhaften Code enthält.
Jetzt müsst ihr nur noch annehmen, dass die Herren Kernel-Programmierer
ihre Kenntnisse aus der vom TE benannten Lektüre bezogen ..
:-]
Übung macht den Meister :-] schrieb:> Jetzt müsst ihr nur noch annehmen, dass die Herren Kernel-Programmierer> ihre Kenntnisse aus der vom TE benannten Lektüre bezogen ..
Unwahrscheinlich, der Kernel funktioniert doch nahezu konsistent!
- Duck und wech -
Yalu X. schrieb:> Damit hat auch Dr. Sommer recht mit seiner Aussage, dass der> Linux-Kernel> fehlerhaften Code enthält.
Kompletter Unfug.
Der Kernel enthält Code, der die Strict-Aliasing-Regeln bricht.
Gleichzeitig schaltet der Kernel-Build aber die Strict-Aliasing-Regeln
ab.
Das bedeutet, dass der Code nicht fehlerhaft ist, sondern bewusst so
geschrieben ist.
Wenn etwas nicht standardkonform ist, heißt das nicht gleich, dass es
fehlerhaft ist.
Ma W. schrieb:> Wenn etwas nicht standardkonform ist, heißt das nicht gleich, dass es> fehlerhaft ist.
Es ist fehlerhaft im Sinne des Standards. Dass der GCC eine Option
bietet über solche Fehler hinwegzusehen ist pure Nettigkeit.
Das ist aber auch kein Beinbruch - wenn man sich des Fehlers und seiner
Folgen bewusst ist und man die entsprechenden Compiler Optionen kennt
ist das akzeptabel. Bleibt nur zu hoffen dass der GCC diese Option nie
entfernt. Das vom Standard garantierte Verhalten wird er aber wohl immer
bieten, d.h. korrekte Programme gehen immer.
Dr. Sommer schrieb:> Es ist fehlerhaft im Sinne des Standards.
Nein. Das Programm ist nicht fehlerhaft.
Das Programm ist nicht standardkonform. Es erhebt auch nicht den
Anspruch standardkonform zu sein. Deshalb kann es auch nicht "fehlerhaft
im Sinne des Standards" sein.
Es ist unmöglich einen OS-Kernel in standardkonformem C zu schreiben.
Ma W. schrieb:> Nein. Das Programm ist nicht fehlerhaft.>> Das Programm ist nicht standardkonform.
Und was für eine Art von Programm ist Standard konform, aber fehlerhaft?
Ma W. schrieb:> Es ist unmöglich einen OS-Kernel in standardkonformem C zu schreiben.
Stimmt auch wieder.
Dr. Sommer schrieb:> Es ist fehlerhaft im Sinne des Standards. Dass der GCC eine Option> bietet über solche Fehler hinwegzusehen ist pure Nettigkeit.
Ich denke das ist falsch.
Strict-Aliasing erlaubt dem Compiler weitere Optimierungen.
Wenn man mit Option no-strict-aliasing compiliert, kann der Compiler
diese betreffenden Optimierungen eben nicht machen.
Wobei ich gelesen hatte, dass es etwas schwierig ist Strict-Aliasing
einzuhalten, und dass die diesbezüglichen Optimirungen auch nicht so
viel bringen, allenfalls einige % mehr performance.
>Es ist unmöglich einen OS-Kernel in standardkonformem C zu schreiben.
Das kann ich mir eigentlich nicht vorstellen.
Stefan schrieb:>>Es ist unmöglich einen OS-Kernel in standardkonformem C zu schreiben.>> Das kann ich mir eigentlich nicht vorstellen.
Wie schreibt man denn Interrupt-Service-Routinen oder Early-Boot-Code in
Standard-C ohne Nicht-Standard-Extensions?
Man wird immer Bestandteile im Kernel haben, die gar nicht
standardkonform sein können.
Ob das Programm fehlerhaft ist, kann nicht beurteilt werden, da nicht
dabei steht, was es tun soll. Wenn die Aufgabe des Programms ist, die
Summe aus 1 und 2 zurückzugeben, ist es fehlerhaft. Soll es das Produkt
aus 1 und zwei zurückgeben, dann ist es korrekt, und der Name der
Funktion zur Berechnung ist nur sehr unglücklich gewählt.
Ma W. schrieb:> Stefan schrieb:>>>Es ist unmöglich einen OS-Kernel in standardkonformem C zu schreiben.>>>> Das kann ich mir eigentlich nicht vorstellen.>> Wie schreibt man denn Interrupt-Service-Routinen oder Early-Boot-Code in> Standard-C ohne Nicht-Standard-Extensions?>> Man wird immer Bestandteile im Kernel haben, die gar nicht> standardkonform sein können.
Ja, das wird man. Deshalb muss aber die Konformität nicht gleich überall
über Bord werfen. Man kann das auch auf die wenigen Stellen beschränken,
wo es nicht anders geht. Linus ist da nur der Meinung, dass sowas nicht
nötig ist, da er ja einen GCC hat, also nutzt er auch alles aus, was der
hergibt. Das musste Intel vor einigen Jahren auch erkennen, als die mal
ihren Compiler dazu befähigen wollten, auch den Kernel übersetzen zu
können. Das war damals ein riesiger Aufwand, weil so viele GCC-Spezifika
kreuz und quer über den ganzen Kernel benutzt wurden.
Linus scheint, wie die obigen Zitate ja zeigen, kein Interesse an
Portabilität oder Standardkonformität zu haben. Wenn es läuft, ist es
für ihn korrekt. Wenn es mit einem neueren, strikteren Compiler nicht
mehr läuft, ist für ihn der Compiler fehlerhaft und nicht das Programm.
Rolf M. schrieb:> Ob das Programm fehlerhaft ist, kann nicht beurteilt werden, da nicht> dabei steht, was es tun soll. Wenn die Aufgabe des Programms ist, die> Summe aus 1 und 2 zurückzugeben, ist es fehlerhaft. Soll es das Produkt> aus 1 und zwei zurückgeben, dann ist es korrekt, und der Name der> Funktion zur Berechnung ist nur sehr unglücklich gewählt.
Unfug. Es ist kein "Fehler," einer Funktion einen Namen zu geben, der
nicht mit dem übereinstimmt, was die Funktion tut. Es ist vermutlich
sinnfrei und irritierend, aber kein Fehler.
Ich sehe in dem Codefragment zwei Fehler:
1. Überlauf nicht berücksichtigt
2. Rückgabe von der main() Funktion ist nicht dazu gedacht, Ergebnisse
einer Berechnung zurückzugeben, sondern dessen exit status.
Adapter schrieb:>> Soll es das Produkt aus 1 und zwei zurückgeben, dann ist es korrekt, und>> der Name der Funktion zur Berechnung ist nur sehr unglücklich gewählt.>> Unfug. Es ist kein "Fehler," einer Funktion einen Namen zu geben, der> nicht mit dem übereinstimmt, was die Funktion tut. Es ist vermutlich> sinnfrei und irritierend, aber kein Fehler.
Und warum ist meine Aussage dann "Unfug"? Ich hab doch genau das gleich
geschrieben.
Rolf M. schrieb:> weil so viele GCC-Spezifika> kreuz und quer über den ganzen Kernel benutzt wurden.
Und du glaubst echt, das wird gemacht, weil man keine Lust hat es
standardkonform zum implementieren?
Hast du mal daran gedacht, dass es gute Gründe hat kein Standard-C zu
verwenden?
>Wenn es mit einem neueren, strikteren Compiler nicht>mehr läuft, ist für ihn der Compiler fehlerhaft und nicht das Programm.
So allgemein ist das natürlich falsch.
Bitte zitiere Linus' Aussage.
Bravo-Leser schrieb:> So so, eine Funktion, die nicht das tut, was ihr Name sagt, ist also> kein Fehler, sondern nur "unglücklich". Naja, Hobbyprogrammierer halt.
Die Funktion sum tut doch genau das, was ihr Name (Abkürzung für "signed
unchecked multiply") sagt:
- sie arbeitet mit vorzeichenbehafteten Werten (signed)
- sie prüft den Wertebereich nicht ab (unchecked)
- sie multipliziert (multiply)
Aber der Name ist tatsächlich ziemlich unglücklich gewählt, da hat Rolf
schon recht ;-)
Ma W. schrieb:> Rolf M. schrieb:>> weil so viele GCC-Spezifika>> kreuz und quer über den ganzen Kernel benutzt wurden.>> Und du glaubst echt, das wird gemacht, weil man keine Lust hat es> standardkonform zum implementieren?
Teilweise ja. Ich hab die Diskussion damals ein bisschen mitverfolgt,
als Intel das gemacht hat. Das war ein Kritikpunkt, den sie am
Linux-Kernel hatten.
> Hast du mal daran gedacht, dass es gute Gründe hat kein Standard-C zu> verwenden?
Ja. Ich zitiere mich mal selbst:
Rolf M. schrieb:> Deshalb muss aber die Konformität nicht gleich überall über Bord werfen.> Man kann das auch auf die wenigen Stellen beschränken, wo es nicht anders> geht.>>Wenn es mit einem neueren, strikteren Compiler nicht>>mehr läuft, ist für ihn der Compiler fehlerhaft und nicht das Programm.>> So allgemein ist das natürlich falsch.> Bitte zitiere Linus' Aussage.
Ich habe mich auf folgende Aussage von Linus bezogen:
***
> The gcc people are more interested in trying to find out what can be> allowed by the c99 specs than about making things actually work.
***
In den folgenden Sätzen beschwert er sich weiter über gcc, weil der ihm
zu standarkonform ist und weil sein nicht standardkonformer Code nicht
mehr damit funktioniert.
Wenn man Konstrukte nutzt, bei denen nicht garantiert ist, dass sie
funktionieren, darf man sich meiner Meinung nach nicht darüber
beschweren, wenn sie einem um die Ohren fliegen. Ich würde in so einem
Fall meinen Code reparieren (oder ggf. auch einen Work-Around suchen),
aber nicht dem Tool die Schuld geben.
Rolf M. schrieb:> Ich würde in so einem> Fall meinen Code reparieren (oder ggf. auch einen Work-Around suchen),> aber nicht dem Tool die Schuld geben.
Natürlich.
Und jetzt kommen wir wieder in der Realität an.
Wenn ein Compiler funktionierenden Code kaputtoptimiert, dann muss es
dafür schon einen guten Grund geben.
Wenn er das nur aus Prinzip tut und keinen Performancevorteil bietet,
dann gehören die Compiler-Entwickler gesteinigt.
Ma W. schrieb:> Wenn er das nur aus Prinzip tut und keinen Performancevorteil bietet,> dann gehören die Compiler-Entwickler gesteinigt.
Damit man den Fehler nicht so schnell findet, und der erst dann auffällt
wenn aufgrund geänderter Umstände die Optimierung dann doch einen
Performance-Vorteil bringt?