Profil für Max > Rezensionen

Persönliches Profil

Beiträge von Max
Top-Rezensenten Rang: 7.683
Hilfreiche Bewertungen: 257

Richtlinien: Erfahren Sie mehr über die Regeln für "Meine Seite@Amazon.de".

Rezensionen verfasst von
Max

Anzeigen:  
Seite: 1 | 2
pixel
C-Programmierung: Unter Linux, Unix und Windows
C-Programmierung: Unter Linux, Unix und Windows
von Helmut Herold
  Broschiert
Preis: EUR 39,90

1 von 2 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen fehlerhaft und inkompetent; unbrauchbar, 29. Mai 2014
Das habilitierte und promovierte Autorenpaar ist auch mit seinem neuerlichen Versuch gescheitert,
ein kompetentes Lehrbuch für C-Anfänger und Fortgeschrittene zu präsentieren.

Die '4. aktualisierte Auflage @2014' der Autoren ist ebenso inkompetent, unvollständig und fehlerhaft wie die Vorgänger.
Zitat: 'Von Anfang an geht dieses Buch dabei intensiv auf C99, den aktuellen Standard für C, ein.'

'Effektive Programmiertechniken aus der Praxis und Hinweise zur Vermeidung von Fallgruben' kündigen die Autoren an,
und scheitern auch damit kläglich.

Im Jahr 2014 vom 'aktuellen' C-Standard C99 zu sprechen, grenzt schon stark an dreiste Ignoranz; bereits seit 2011 existiert als
aktueller Standard ISO C11 (mit Technical Corrigendum 1 vom 15.7.2012), von den Autoren vollständig ignoriert und unerwähnt.

'Von Anfang an...' ist auch vollständig unzutreffend, es werden die 3 vorigen Auflagen des Buches (die sich ausschließlich auf C89 orientieren)
lediglich um ein paar kleine C99 Kapitel ergänzt. Die Änderungen von C99 bzgl. C89 bleiben unberücksichtigt, diese 'alten' Kapitel
sind somit in mehreren Fällen schlichtweg falsch, weil inkonform zum C99-Standard.
Oftmals widersprechen diese kurzen C99-Kapitel den unmittelbar zuvor gemachten Aussagen, die Autoren haben sich wie gesagt, nicht die Mühe gemacht,
die C89 Kapitel anzupassen; der Leser muss jederzeit darauf gefasst sein,
für das aktuelle Thema eine Seite weiter grundsätzliche Einschränkungen vorzufinden.

Das gilt z.B. für die implizite Funktionsdeklaration, die in C89 galt; hier werden zunächst umfangreiche, mehrseitige Abhandlungen vorgenommen, um anschließend festzustellen, dass in C99 diese implizite Funktionsdeklaration nicht mehr gilt; die Autoren beschreiben nur lapidar:
'es wird vom Compiler aber trotzdem übersetzt'.

Didaktisch haben die Autoren im Lauf der Auflagen auch nichts dazu gelernt, nach dem einführenden "hello world"-Beispiel erklären sie erst viele Kapitel später in der Buchmitte, was main() und #include bedeuten.

Ebenfalls bleiben wichtige englische Fachbegriffe aus dem Standard im ganzen Buch unerwähnt (compound statement,compound literal,undefined behavior,sequence point,lvalue,rvalue,...).
compound literals werden exotisch als
unbenamte Arrays
(int[]){}
oder unbenamte Structs
(struct){}
bezeichnet.
Auch die Wortschöpfung der Autoren "Alt-C" für das bekannte K&R-C aus Pre-ANSI Zeiten gibt Rätsel auf.

Konformes und strikt konformes Verhalten ist den Autoren unbekannt, sonst hätten sie nicht behauptet, C99 kompatible Programme wären 'ohne große Änderungen compilierbar auf anderen Systemen', und für strikt konforme Programme hätten sie dann 'OHNE Änderungen compilierbar auf anderen Systemen' beschreiben können.

Die Kommentarvarianten /**/ und // werden vorgestellt, ohne Hinweis auf die 'Fallgrube' der Verwendung beider Varianten miteinander.

Unsicherheit auch bei den Basis-Datentypen,
- "Datentyp char wird meist durch 1 Byte realisiert" -> das ist immer der Fall
- char: 1 Byte = 8 Bit -> falsch, der Standard schreibt CHAR_BIT vor
- Signifikanz von Variablennamen vergessen und Unterschiede zw. C89 und C99
- Verlust von Bits bei zu großen Zahlen:
... werden abgeschnitten -> richtig ist: bei unsigned Typen wrap around , bei signed impl.def.
- im Beispiel wird behauptet:
int i = 3000000000; /* Da 3000000000 nicht in int-Bereich passt, wird hier mit unsigned gerechnet */
falsch:
C89 int -> long -> unsigned long
C99 int -> long -> long long
In C99, auf das die Autoren doch 'intensiv' eingehen wollten, kommt es also nicht zu einem Fehler, weil in long long umgewandelt wird (und nicht in unsigned).
Es erfolgt auch kein Hinweis zur Umgehung des Problems mit Typ-Suffixen:
LL oder ULL oder Cast (long long)

- bei Fließkommatypen erfolgt kein Hinweis auf IEEE 754, die ab C99 vorhandene Prüfung mittels __STDC_IEC_559__ bleibt unerwähnt
Dabei werden laienhafte 'Tipps' gegeben:
int a,b;
float halbe = a/b;
float halbe = (a+0.0)/b; // Tipp
Das ist Unsinn, weil unnötiger zusätzlicher Laufzeitcode erzeugt wird, dabei wollten die Autoren doch Techniken aus der 'Praxis' zeigen;
dort verwendet man üblicherweise
(float)a/b;
bzw.
(double)a/b;

Das Leeren des Eingabestreams stdin mittels 1x getchar() nach scanf gehört auch zu den 'Praxis'-Tipps der Autoren;
sie 'vergessen' hierbei zu erwähnen, dass nur eine Schleife mit getchar() in jedem Fall dieses Problem löst.

Bei der Falle "Semikolon nach for" in Fällen wie
int i;
for( i=0; i<10; i++ );
printf("%d",i);
geben die Autoren dann auch konsequenterweise keine Tipps zur Vermeidung, da sie die praxisübliche Variante der internen for-Variablendefinition zwar kennen und in einem Kapitel vorstellen, aber auch hierbei sind sie unfähig, dieses neue Sprachfeature aus C99 anzuwenden:
bei
for(int i=0; i<10; i++ );
printf("%d",i);
würde der Compiler abbrechen, da i nicht im Scope von printf liegt.

Die üblichen Anfängerfehler bei printf/scanf kommen vor:
printf("%d",sizeof(...));
statt C99 korrekt
printf("%zu",sizeof(...));
Erwähnen braucht man nicht, dass die Autoren zwar "%zu" für den Datentyp size_t nennen, es aber wiederum versäumen,
dieses C99 Feature in ihrem (aus Vorgängerauflagen stammenden) C89-Code anzuwenden.

Bei scanf ist es ähnlich:
char a[50];
scanf("%s",a);
Im gesamten Buch fehlt die Anwendung der Längenbegrenzung für Strings bei scanf mittels:
scanf("%49s",a);
und auch hier wieder: die Autoren nennen die Längenbegrenzung in ihrer Tabelle bei scanf, wenden sie aber nicht an.
Ebenso verwenden sie in ihren Beispielcodes nahezu nie den Returnwert bei scanf; offensichtlich sind sie auch hier der Meinung, dass sowas in der 'Praxis' unnötig wäre.

Bei
while( (zeich=getchar())!=EOF )
wird behauptet, EOF wird bei Dateiende geliefert ohne Hinweis darauf, dass dies auch bei Lesefehlern vorkommt.
Später im Buch bei fgets liefern die Autoren dann diese Information, der Leser kann aber zuvor nicht wissen, dass diese Information folgt;
und da zeigt sich wieder der inhomogene Aufbau des Buches: die Autoren haben den Überblick verloren, sie sind nicht in der Lage, zusammengehörende Informationen auch zusammengefasst darzustellen; diese nicht vorhandene Didaktik ist für die habilitierten/promovierten Autoren schon peinlich zu nennen.

Die Autoren sind sich auch nicht zu schade, Funktionen der Standardbibliothek zu verändern:
#include <time.h>
#define srand(s) z=s
int main()
...
srand(time(NULL));
Hierbei 'reimplementieren' sie srand, ein absolutes Tabu in der von den Autoren oft strapazierten 'Praxis'.

Die Autoren verwenden häufig globale Variablen, obwohl sie selbst auf die überwiegenden Nachteile hinweisen.
Das gilt auch in anderen Fällen, z.B.
verwenden sie gets, obwohl sie zuvor davon warnen oder
die Gleichheitsprüfung von Fließkommazahlen: sie warnen davor, verwenden es aber trotzdem in ihren Beispielen.
Die laienhafte Programmierung stellt sicherlich die Kompetenz der Autoren wiederum in Frage, ebenso:
ungeniert schreiben die Autoren in String-Literale (beispielhaft):
char *satz[] = { "abc", "def", "ghi" };
satz[0][0]='x';
compilieren das dann mit
cc -fwriteable-strings
mit der Anmerkung, dass der Compiler dafür sorgt, dass die Bereiche beschreibbar sind. Sie nutzen also spezielle Compilereinstellungen um undefiniertes Verhalten zu umgehen.

Weitere Anfängerfehler zeigen die Autoren bei qsort in der compare-Funktion:
return (*(int*)zahl2 - *(int*)zahl1);
Das ist fehlerhaft für Werte in der Nähe der int-Grenzen INT_MAX, INT_MIN, weiterhin wird der const-Qualifizierer weggecastet.
Auch behaupten die Autoren, qsort implementiere den Quicksort-Algorithmus: tatsächlich schreibt der Standard dies aber nicht vor, ebenso wie er nicht vorschreibt, dass qsort stabil sortiert.
Das Thema stabile Sortierung ist aus Sicht der Autoren offenbar auch nicht praxisrelevant, deshalb klammern sie das Thema vorsorglich ganz aus.

Immer wieder kommen falsche Behauptungen und unbrauchbare Tipps:

- Ein modulglobales Objekt ist innerhalb der gesamten Programmdatei (Modul) ansprechbar, in der es deklariert ist... -> richtig ist: ... definiert ist ...
- strtok: kein Hinweis auf "Falle" Nichtreentranz/nicht multithreading-fähig und dass der Ausgangsstring dabei verändert wird
- Initialisierung lokaler Variablen auch mit Nicht-Konstanten: falsch, lokale static Variablen muss nach wie von konstant initialisiert werden
- char falsch[] = {'f','a','l','s','c','h','\0'};
entspricht den folgenden Angaben
char *falsch = "falsch";
char falsch[]= "falsch";
-> falsch, die char* Variante entspricht dem nicht
- in Beispielen setzen die Autoren die kontinuierliche Folge 'A'..'Z' , 'a'..'z' von char-zeichen voraus, was vom Standard nicht garantiert ist
- continue soll man nicht verwenden stattdessen if
- ... dass in jedem Modul alle dort aufgerufenen Funktionen, die keine int-Werte zurückliefern,
mit Typangabe und extern vor dem eigentlichen Aufruf zu deklarieren sind
- "zu Dokumentationszwecken" empfehlen die Autoren einen Cast bei malloc
char *zgr;
zgr = (char*)malloc(MAX_ZAHLEN * sizeof(char));
ohne auf die Gefahren solcher Casts in anderen Fällen als malloc hinzuweisen; es werden dadurch Compilerwarnungen unterdrückt -> keine 'praxisnahe' Empfehlung für Anfänger

Bei free fehlt der Hinweis auf die Gefahren bei doppelter Freigabe desselben Speichers und es folgt mal wieder
der untaugliche Tipp zur Vermeidung der 'Fallgrube':
#define FREE(zgr) { \
if(zgr != NULL) { \
free(zgr); \
zgr=NULL; \
} \
}
Durch dieses explizite NULL-Setzen werden Laufzeitfehler unterdrückt, die auf Designfehler hinweisen und es führt
weiterhin zu Verschleierung von Fehlern, falls der Zeigerwert zuvor kopiert wurde: diese Kopien bleiben unverändert und werden zwangsläufig zu Fehlern führen.

Das Programmdesign ist allgemein auch nicht die Stärke der Autoren, neben den schon genannten Widersprüchen in ihren Aussagen und den Beispielcodes verwenden sie oftmals über das ganze Buch verteilt unterschiedliche Implementierungen für dieselbe Aufgabe, bubblesort ist hier nur ein Beispiel.
Es fehlt dem Buch eindeutig an Konsistenz und Konsequenz.

Der Tipp zu Implementierungsdetails unter Windows geht auch daneben:
die Autoren behaupten nämlich wiederholt, das Linefeed '\n' werde durch \n\r (ASCII 10+13) ersetzt;
unter Windows ist es jedoch \r\n und 13+10; soviel zum Thema Praxisrelevanz der Autoren.
Wenn sie schon auf Besonderheiten für Windows hinweisen, hätten sie wenigstens auf die Besonderheit von fopen/EOF für Textfiles hinweisen sollen;
liegt nämlich ein CTRL+Z (0x1a) vor, beendet ein FILE-Stream im Textmodus die Bearbeitung hier.
Stattdessen behaupten sie, unter Linux gäbe es diesbezüglich keine Probleme; naive Unkenntnis auch hier: gerade UNIX/Linux-Systeme dienen oftmals als Server für viele Arten von Textdateien- und Streams unterschiedlichster Herkunft;
es gibt also sehr wohl auch unter Linux Besonderheiten, die 'in der Praxis' zu berücksichtigen sind.

Fazit:
Die Autoren sind mit ihrem Versuch, ein praxisrelevantes, 'intensiv' auf C99 basierendes Buch für Anfänger und Fortgeschrittene zu schreiben, kläglich gescheitert.
Das Buch enthält viele Fehler in Erläuterungen und Beispielcode, die 'Tipps' zur angekündigten Vermeidung von 'Fallgruben' sind überwiegend unbrauchbar und unvollständig.
Das Buch ist inhomogen aufgebaut, der Leser wird oftmals in die Irre geführt.
Das Buch ist der gescheiterte Versuch der Autoren, ihre vorigen Auflagen auf C99 anzupassen; ein paar kleine C99-Kapitel anzuhängen reicht eben nicht;
man muss Grundverständnis aufbringen, was sich im Standard geändert hat und dieses präsentieren.
Dieses Werk ist niemandem zu empfehlen.
Kommentar Kommentar (1) | Kommentar als Link | Neuester Kommentar: May 30, 2014 10:52 AM MEST


Programmieren in C: Programmieren lernen von Anfang an - Mit vielen Programmierbeispielen - Geeignet zum Selbststudium
Programmieren in C: Programmieren lernen von Anfang an - Mit vielen Programmierbeispielen - Geeignet zum Selbststudium
von Heimo Gaicher
  Taschenbuch
Preis: EUR 24,90

15 von 21 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen beispielloser Unsinn; katastrophal, 22. November 2013
Das Buch ist eine einzige Katastrophe, es ist niemandem zu empfehlen.
Genauso schlecht wie das Papier ist auch der Inhalt.
Der Autor wendet sich an Einsteiger und empfiehlt das Buch zum Selbststudium, d.h. bei einem solchen Studium sind keine Rückfragen möglich, alles im Buch muss klar und widerspruchsfrei sein: nichts von alledem kann der Autor erfüllen.

Didaktisch ist das Buch ebenso eine Kastastrophe, hinsichtlich der Reihen der Themen, Erklärungen und Beispielcodes.
Übergangslos und ohne Erläuterungen werden Codeteile gezeigt, vielfach werden sie im ganzen Buch auch später nicht erläutert, wenn überhaupt.
Das gilt z.B. für den Adressoperator &, fflush(stdin), den Datentyp long double, die Funktion getchar() und main().

Der Autor arbeitet ausschließlich mit VisualStudio2010-Express.
Hier passiert dann schon wieder ein Fehler, indem er behauptet, VSE sei Freeware. Das ist falsch, VSE ist Lizenzsoftware, um eine Lizenz zu erhalten muss man sich persönlich registrieren, wenn auch bisher kostenfrei.

Bei der Beschreibung der Projektumgebung in VSE begeht der Autor den gravierenden Fehler, dass er statt einer C-Programmierumgebung eine C++-Programmierumgebung erzeugt, (main.cpp statt richtig main.c bzw. explizite Compileroption /TC), C++ ist eine andere Sprache als C.
Der Autor merkt in all seinen Beispielen nicht, dass er mit C++ arbeitet, das ist laienhafter Unsinn, der zwangsläufig zu weiteren Fehlern führt, siehe unten.

Der Autor begeht durchgängig im Buch den Fehler der Verwechselung von Definition mit Deklaration,
den C-Standard C99 erwähnt er nur einmal mitten Buch und am Ende:
"Um die Bibliotheken des C99-Standards nutzen zu können, muss der verwendete Compiler diesen Standard auch unterstützen!",
dabei unterstützt VisualStudio gar kein C99, das 'verschweigt' er dem Leser offensichtlich aus Unwissenheit und wie gesagt, er arbeitet mit einem C++-Compiler, der unterstützt eben nur C++ Standards.
Was ein Standard ist, was er normt, welche Standards es gibt (C89,C99,C11), worin sie sich prinzipiell unterscheiden, erwähnt der Autor nicht.
Der Autor verwendet ständig fflush(stdin), was alle Standards verbieten: seine ganze Naivität kommt zum Ausdruck:
"Es kann aber sein, dass dies nicht bei jedem Betriebssystem gelingt", unklar ist, warum er selbst anschließend sagt
"da fflush für inputstreams aber nicht definiert ist, kann es zu Problemen führen" und einmal die korrekte Lösung mittels getchar-Schleife zeigt.
Warum wendet er diese korrekte Lösung dann nicht überall an?
Sowas weist nur wieder auf die Verständnislosigkeit des Autors beim C-Standard hin, er widerspricht sich ständig und weiß nicht, ob und was er zuvor gesagt hat: deshalb wiederholt er auch häufig vorher Gesagtes, und dabei auch Fehler.
Beispielweise führt er an, dass Variablennamen mit Schlüsselworten nicht kollidieren dürfen, nennt aber die C-Schlüsselworte erst mehrere Seiten später im anderen Zusammenhang und ohne vorher den Leser zu informieren; der Leser kann nicht wissen, dass diese Infos anschließend folgen und wird an der Stelle zuvor mit seinen Fragen allein gelassen.
Die Notwendigkeit der Auswertung der scanf-Returns (zur Fehlerkontrolle) erklärt der Autor erst nahezu am Ende des Buches, nachdem er zuvor niemals bei scanf den Returnwert auswertet.

Wenig überraschend ist dann auch, dass der Autor die üblichen Anfängerfehler macht:
- Variablennamen beginnend mit _ ( nicht standardgemäß )
- falsche Formatspezifizierer bei printf ( %d für size_t und Pointer )
- casten von malloc-Aufrufen ( der Autor verwendet ja C++, wo dies nötig ist; in C ist dies unnötig )
- Behauptung, dass float 6 Stellen Genauigkeit hat -> Standard schreibt hier FLT_DIG vor
- "scanf überprüft nicht, wieviele Zeichen eingegeben wurden" -> falsch, scanf kann die Länge begrenzen
- wenn er nicht mehr weiter weiß, verwendet der Autor globale Variablen ohne Hinweis auf die Nachteile
- der Autor zeigt Code mit eindeutigem undefinierten Verhalten (UB) u.a. bei:
char text[5]; printf("%s",&text); statt richtig printf("%s",text);
char name[20]; scanf("%s",&name); statt richtig scanf("%s",name);

Nicht zu erwähnen braucht man, dass der Autor keine gängigen C-Fachbegriffe nennt und erklärt und Schreibfehler vorkommen wie
typdef statt richtig typedef
strol statt richtig strtol

Sinnfrei sind auch Aufgaben wie "Die Dezimalzahl 200 soll in eine Binärzahl umgerechnet werden...", eine Zahl bleibt immer dieselbe, unabhängig von ihrer Darstellung - da gibt es nichts 'umzurechnen'.

Beim Thema der Auswertungsreihenfolge der logischen Operatoren 'verzichtet' der Autor auf den Hinweis zum short circuit;
im gesamten Buch ist auch nirgends die Tabelle mit den Vorrangregeln der C-Operatoren genannt - unverzichtbar in einem Lehrbuch.

Der Autor erwähnt zwar Linux und Embedded Systeme als zusätzliche Anwendungsgebiete von C und hebt die Portabilität von C dabei hervor:
sein gezeigter Code ist aber ausschließlich mit VSE und nur unter Windows lauffähig, u.a. auch mit dilettantischen und unportablen Versuchen, die Konsolenausgabe zu manipulieren wie:
system("color 0c");

Beispiellosen Unsinn zeigt der Autor mit:

void berechnung(int&x){...}

und der anschließenden 'Erklärung' von call by reference:
diese gezeigten Referenzen sind ausschließlich ein Sprachmittel von C++, sie in einem C-Lehrbuch zu zeigen ist beispiellos in der Literatur und zeigt wiederum das laienhafte Verständnis des Autors von C-Programmierung: er kann C++ nicht von C unterscheiden, er merkt diesen Unsinn wegen eigener Inkompetenz nicht und praktiziert offensichtlich Programmieren durch Ausprobieren (alles was der Compiler erlaubt, wird schon richtig sein...).

Auch bei weiteren Erklärungsversuchen zu einfachsten Beispielcodes scheitert der Autor kläglich:

int a=2;
int *ptr1=&a;

printf("Die Speicheradresse von a =%d",&ptr1); // UB wegen falschem Specifier und zusätzlich falsch ist &
printf("Die Groesse von a = %d Byte",sizeof(&ptr1)); // wieder UB, angezeigt wird die Größe eines Zeigers auf einen int-Zeiger und nicht die Größe von int

Im gesamten Buch fehlen allgemeine Hinweise zum Programmdesign, wann verwendet man Funktionen, wie teilt man in Module auf, wie kapselt man Daten usw.
Im Anhang fehlt eine vollständige Referenz der Standard-Bibliotheksfunktionen, zum Nachschlagen taugt das Buch somit auch nicht.

Fazit:
Der Autor ist aufgrund seiner laienhaften Vorstellung von C-Programmierung eindeutig überfordert damit, ein Buch über C-Programmierung zu schreiben.
Der größte Teil von Beispielcodes und Erläuterungen ist falsch und/oder nicht standardkonform.
Der Autor ist sich nicht bewusst, dass er in C++ programmiert, und das in einem Buch über C-Programmierung.
Das Buch ist niemandem zu empfehlen, niemand wird anhand dieses Buches die Programmierung in C im Selbststudium erlernen können.
Kommentar Kommentare (9) | Kommentar als Link | Neuester Kommentar: Jul 18, 2014 6:56 AM MEST


C im 21. Jahrhundert (Buch mit E-Book)
C im 21. Jahrhundert (Buch mit E-Book)
von Ben Klemens
  Gebundene Ausgabe

19 von 21 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen Inkompetenz und Täuschung; eindeutig nicht zu empfehlen, 18. November 2013
Das Buch ist eine einzige Mogelpackung.

Zitat: "Werfen Sie Ihre Vorstellungen von C über Bord und lernen Sie eine Programmiersprache neu kennen...
Mit 'C im 21.Jahrhundert werden Sie aktuelle Techniken entdecken, die in keinem anderen Buch über C zu finden sind".
Diesem Anspruch wird das Werk eindeutig nicht gerecht, kein Leser wird nach Lektüre dieses Buches grundlegend Neues erfahren haben.
Das Buch ist niemandem zu empfehlen, auch wegen der Inkompetenz des Autors zu Fragen der C-Standards und Fehlern in seinen Beispielcodes.

Die ersten 100 Seiten befassen sich ausschließlich mit allgemeinen Betrachtungen zum Handling von C-Programmen/Projekten, autotools, make, Git usw. werden vorgestellt, nicht ohne das schon genannte Eigenlob des Autors.
make gibt es bekanntlich schon seit es Unix gibt, und Git-Vorgänger basierend auf CVS gab es schon in den 80ern, es kann also keine Rede von Neuigkeiten aus dem 21.Jahrhundert sein.
Als Standard setzt der Autor C99 voraus.
Für Windows empfiehlt der Autor cygwin/MSYS, als Compiler gcc und clang. (wobei er richtig darauf hinweist, dass mit cygwin1.dll auch die Quelltexte ausgeliefert werden müssen, es sei denn, man erwirbt eine (kostenpflichtige) Lizenz).
Praxisunkenntnis offenbart sich schon hier:
- "für fork und popen benutzen Sie unter Windows MinGW" -> MinGW unterstützt kein fork
- int x[20]={}; -> Syntaxfehler gemäß Standard wegen leerer Initialisierer-Liste

Der Autor setzt ausschließlich auf die Kommandozeile, IDE nennt er zwar, ist aber offensichtlich der Meinung, dass man im 21.Jahrhundert keine IDE (mit konfigurierbaren Kommandozeilentools oder eigener Projekt- und Sourcecodeverwaltung) einsetzen sollte; vielfach wird das Makefile mit aufgeführt.

Allgemeine Weisheiten wie "benutzen Sie einen Debugger" oder "benutzen Sie valgrind" (wobei er verschweigt, dass valgrind für Windows nicht existiert) tragen ebenso wenig zur Seriösität der Autor-Aussagen bei.
Allseits (und schon im 20.Jahrhundert bekannte) 'Tipps' werden gegeben, wie
./configure
make
make install
ebenso der Hinweis auf
LD_LIBRARY_PATH
zur Runtime-Konfiguration: alles bekannte Details und durchaus "auch in anderen Büchern zu finden".

Allgemeine Ratschläge des Autors, man solle vor Beginn eigener Projekte zunächst nach schon vorhandenen C-Bibliotheken suchen (der Autor zählt z.B. auf: pthreads, GLib, GNU libiberty, GSL, cURL, libxml, SQLite) und diese dann vorzugsweise vor eigenen Implementierungen verwenden, haben schon im 20.Jahrhundert gegolten und stellen auch keine 'neue Technik' dar.
Im Kapitel "Ein Dictionary implementieren" hält sich der Autor dann selbst nicht daran; nachdem er zuvor GHashTable aus GLib gezeigt hat, nimmt er doch wieder eine eigene Implementierung vor, und die dann auch noch mit Verwendung laienhafter globaler Variablen.

Weiterhin kündigt der Autor im ersten Teil des Buches MEHRFACH an, dass er später im Buch 'ultimative' Verfahren zum Stringhandling zeigen wird und dass malloc dabei und auch sonst vollkommen unnötig ist;
nichts von diesen Versprechungen kann der Autor einhalten, da er in nahezu jedem Beispielcode doch wieder malloc usw. verwendet.
Er führt auch selbst 5 Ausnahmen auf, wo doch der Einsatz von malloc notwendig ist;
dabei ist eine obskure Beschreibung, dass man für größere Speicherbereiche, deren Größe man erst zu Laufzeit kennt, doch malloc einsetzen muss, dies aber 'meistens in eigene Funktionen kapselt'; ein malloc-Aufruf in einer eigenen Funktion ist nach Ansicht des Autors offenbar kein-malloc Aufruf.
"...Auch hier werden Sie vermutlich Ihre Daten in einer Art Objekt speichern, sodass dies in der Praxis zu einem Aufruf der Funktion object_new führen wird und weniger zum Aufruf von malloc selbst".
Äußerst unüblich ist es auch, bei malloc von 'manueller' Speicherreservierung zu sprechen (wie es der Autor im ganzen Buch nennt): gängig ist hier, von 'dynamischem' Speicher zu reden.

Überhaupt verwendet der Autor sehr wenig konkreten Code in seinem Werk (was er auch so beschreibt und offensichtlich so beabsichtigt).

Auch in den wenigen Beispielcodes offenbart sich die Unsicherheit und Praxisferne des Autors, noch nicht mal simple Grundlagen kann er vermitteln, weder im Code selbst noch in seinen umfangreichen Erläuterungsversuchen:

- er verwechselt ständig Deklaration mit Definition (greift auch schon mal fehl, indem er beschreibt, wie man eine deklarierte Variablen initialisiert, was unmöglich ist)
- "der Typ size_t ist dazu gedacht, Adressen als Integer-Wert zu speichern" -> Unsinn, size_t soll Längen/Größenangaben aufnehmen, siehe auch strlen
- zeigt sorglos Gleichheitsvergleiche von double mit ==, ohne Hinweis der Besonderheiten
- setzt häufig assert ein (ohne jeglichen Hinweis auf NDEBUG; bei vielen Compilern wird assert im Release-Modus ignoriert, d.h. der Code nicht ausgeführt)
- der Autor zeigt den Vergleich von struct-Variablen mit memcmp, ohne auf die Risiken der (implementierungsabhängigen) padding-Bytes hinzuweisen; das Padding erwähnt er erst später
- übergangslos werden VLA eingeführt ohne die Unterschiede zu herkömmlichen Arrays oder den Begriff VLA selbst zu nennen und ohne Erwähnung, dass diese in C11 nur noch optional vorhanden sind
- im ganzen Buch werden die Fachbegriffe String-Literal und undefined behavior (UB) nicht genannt
- String-Literale werden vom Autor niemals mit const char *s="hello"; verwendet, sondern nur ohne const; und das, obwohl der Autor später empfiehlt, oft const einzusetzen: warum setzt er es dann selbst nicht ein?
- Nachteile von Verwendung von static wird am Beispiel von strtok mit C11 _Thread_local abgetan, die neben den Thread-Problemen ebenso vorhandenen Reentranz-Probleme werden vom Autor überhaupt nicht erwähnt; der lapidare Hinweis geht nur auf strtok_r,strtok_s,strsep ein
- auch Alternativen zu strtok( "\t\r\n") 'vergisst' der Autor zu erwähnen, wie sscanf(string,"%s",s), wobei hier der Ausgangsstring nicht zerstört wird, was meistens vorteilhaft ist
- er verwechselt auch schon mal POSIX mit ISO-C, z.B. bei fopen/open POSIX/ISO statt richtig ISO/POSIX
- der Autor verwendet grundsätzlich strcasecmp (POSIX) statt das gebräuchliche ISO-konforme strcmp
- der Autor behauptet, CHAR_BIT sei in C89 impl.abh. und in C99/C11 == 8 -> falsch, in jedem Standard ist CHAR_BIT >= 8 vorgeschrieben
- get_opt wird vom Autor gezeigt, ohne Hinweis, dass dies nur POSIX vorhanden ist (und dort getopt heißt und nicht get_opt)
- der Autor behauptet, IEEE 754 sei nicht vom Standard definiert -> falsch, C99 definiert __STDC_IEC_559__, womit sogar ein Test auf IEEE-754 Konformität erfolgen kann
- auch mit den Grundlagen Array/Pointer hat der Autor (ebenso wie mit Deklaration/Definition) seine Schwierigkeiten, indem er behauptet:

double *plist = (double[]){1,2,3};
plist sei ein Zeiger auf ein Array (von double) -> falsch, plist ist ein Zeiger auf double

Der Autor ist sich auch nicht zu schade, konkrete angebliche Vorgaben aus dem Standard zu nennen:
"... der Standard legt fest, dass der Inhalt von konstanten Strings (so nennt der Autor String-Literale) auf jeden Fall schreibgeschützt sein muss..."
das ist auch wieder falsch interpretiert, der Standard spricht nur von undefiniertem Verhalten bei Änderung eines Elementes eines String-Literals.

In Kapitel "Das Problem mit char const**" offenbart sich dann die Naivität des Autors im Umgang mit Selbstverständlichkeiten wenn er schreibt:

int *var;
int const **constptr = &var;
"Bei einer Folge von Zeigern konvertieren alle mir bekannten Compiler den 'obersten' Zeiger nach const..."

Der Autor praktiziert also Programmieren durch Ausprobieren, anstatt die klaren Vorgaben aus dem Standard zu begreifen und zu präsentieren.
(in diesem Fall wird nichts 'konvertiert', der Compiler warnt, weil der einem Zeiger zugrundeliegende Datentyp 'hier also int const*' nicht kompatibel zu 'int *' ist, und der Standard vorschreibt, dass Zeiger nur kompatibel sind, wenn der basierende Datentyp kompatibel ist;
'const int' und 'int' sind kompatible Typen, also wären 'const int*' und 'int*' kompatibel, und der Compiler warnt nicht)

Alle möglichen String-Problematiken in C möchte Autor mit asprintf (weder ISO noch POSIX, nur GCC-Extension) erschlagen, häufig mit variadischen Makros.
Er meint dadurch malloc/free umgehen zu können (wie er es ja am Beginn des Buches versprochen hat), muss aber dann doch in seinen präsentierten Makros zumindest free einsetzen (für das erste Argument bei asprintf) um Speicherlecks zu vermeiden, und beim ersten praktischen Anwendungsfall eines Stringarrays verwendet er dann doch wieder ganz ungeniert malloc/realloc;
(also auch hier wieder entgegen dem ursprünglichen 'Versprechen', immer ohne malloc auszukommen und 'neue' Programmiertechniken in C für das 21.Jahrhundert vorzustellen, die noch in keinem anderen Buch vorkommen).
Solche Stringarrays sind in C schon seit Bestehen üblich, hier ist nichts 'neu'.

Beim Beispiel zur printf-Ausgabe von struct-Variablen stellt der Autor umständlich eine eigene, wieder mal auf Makros basierende Variante vor, und nicht die GCC-Extension register_printf_function, die genau diese Aufgabe übernimmt; schließlich ist des Autors allumfassende asprintf-Funktion zum Stringhandling auch nur eine GCC-Extension und kein Standard, offensichtlich besitzt der Autor auch keinen Überblick über die GCC-Features außerhalb von asprintf.

Simple kurze Beispiele gelingen oft nicht, z.B. beim Beispielprogramm zu rekursiven Dateinamenausgabe

if (entry->d_name[0]=='.') continue; // hier werden fehlerhaft Verzeichnisse mit '.' beginnend ignoriert, z.B. .ssh/

oder

if (entry->d_type==DT_DIR) // hier verstößt der Autor gegen die POSIX-Portabilitätsvorgaben, die S_ISDIR vorschreiben

Bei Datenstrukturen verweist der Autor auf GHashTable aus glib.h und verwendet auch hier in seinem Beispielprogramm auch wieder malloc (was doch angeblich 'niemals' gebraucht wird).

Weiterhin verweist der Autor beim Thema "anonyme Strukturelemente" auf C11, um dann im praktischen Beispiel doch wieder auf die herkömmlichen unions zurückzugreifen, die gewiss kein neues Feature des 21.Jahrhunderts darstellen, sondern seit Bestehen von C existieren und auch vielfach in anderen Büchern vorkommen.

Fazit:
Der Autor macht falsche Versprechungen, die er in seinem Buch nicht hält; der Autor verfügt über mangelndes Grundlagen- und Standardverständnis in C, was dazu führt, dass seine vorgestellten Beispielcodes oftmals fehlerhaft sind, ebenso wie seine Erläuterungen.
Keinesfalls führt der Autor 'neue Programmiertechniken des 21.Jahrhunderts' auf, die man 'in keinen anderen Büchern' finden kann.
Seine 'Tipps' sind überwiegend schon seit langem bekannt, entweder seit Bestehen von C, zumindest aber im 20.Jahrhundert.
Das Buch ist von vorn bis hinten eine dreiste Mogelpackung und da hat der Autor mal recht: so etwas ist nicht oft in anderen Büchern zu finden.
Das Buch ist niemandem zu empfehlen.
Kommentar Kommentar (1) | Kommentar als Link | Neuester Kommentar: Dec 7, 2013 7:14 PM CET


C - Lernen und professionell anwenden: Mit Microsoft Visual Studio Express 2012 und Open Watcom-Compiler auf der DVD (mitp Professional)
C - Lernen und professionell anwenden: Mit Microsoft Visual Studio Express 2012 und Open Watcom-Compiler auf der DVD (mitp Professional)
von Ulla Kirch
  Taschenbuch
Preis: EUR 29,95

4 von 7 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen schlecht, inkompetent, unbrauchbar, 29. August 2013
Die Autoren sind mit ihrem eigenen Anspruch gescheitert, ein Lehrbuch zur "professionellen" Programmerstellung mit C zu veröffentlichen.
Weder kann jemand nach Lektüre dieses Buches professionelle Anwendungen erstellen noch stimmt die Aussage der Autoren,
sie hätten den neuesten C11 Standard als Grundlage für ihr Buch gewählt.
Es gehört mehr zu einem selbstgesteckten Ziel "Die Sprachbeschreibung des Buches basiert auf dem neuen C-Standard C11" als die Auflistung der neu hinzugekommenen Bibliotheksfunktionen - eben die Neuheiten des Sprachumfanges selber sind den Autoren ganz offensichtlich unbekannt - sonst hätten sie diese erwähnt oder zumindest gekennzeichnet - wie sie es am Beginn auch selbst versprechen.
Das Buch ist eine lieblose Aufblähung der vorhergehenden Auflagen des Buches durch die Autoren - es enthält nach wie vor essentielle Fehler in der Darstellung der C-Grundlagen und bei den gezeigten Beispielcodes. Die Autoren sind auf dem C89-Standard ihrer vorherigen Buchauflagen stehengeblieben.
Lapidare Aussagen der Autoren wie - der C11 Standard wird noch nicht von allen Compilern unterstützt - zeigen das Unverständnis der Autoren in der Praxis des Umganges mit Compilern - sie "vergessen" den Leser darauf hinzuweisen, dass der dem Buch beigelegte Microsoft C-Compiler aus VisualStudioExpress 2012 den C11-Standard und auch den C99-Standard überhaupt nicht unterstützt; der Compiler ist auf dem Stand des ersten C-Standards C89 stehengeblieben, genauso wie die Autoren mit ihrem Wissen; dies muss der Leser also selbst herausfinden - was für ein Lehrbuch schon ziemlich peinlich ist.

Weitere Peinlichkeiten leisten sich die Autoren, indem sie behaupten, ihr Buch sei eine "vollständige" Einführung in C, viele in C99 hinzugekommene Eigenschaften werden gar nicht erwähnt oder im Beispielcode falsch angewendet bzw. allgemein falsch dargestellt - auch hier wieder sieht man deutlich, dass die Autoren beim C89 Ur-Standard stehengeblieben sind und eben gerade nicht den eigenen Anspruch nach C11 Konformität gerecht werden.

"C ist an der Architektur der heutigen Rechner orientiert" wird behauptet, was grundlegend falsch ist.
C ist vom Sprach- und Bibliotheksumfang her sehr klein, eben damit es sich auf viele mögliche Hardwareplattformen portieren lässt und dabei ist es gerade unmöglich, auf aktuelle Hardwarespezialitäten einzugehen.
Als Beispiel sei Multithreading genannt, welche zu Entstehungszeit von C 1972 völlig unbekannt war, und C durch statische Bibliotheksfunktionen und Variablen diesem (heute aktuellen) Prinzip zuwiderläuft.
Widersprüchlich handeln die Autoren schon bei den Grundlagen, indem sie im Text sagen, dass die Größe von ganzzahligen Datentypen (short,int,long,long long) nicht definiert ist, gleichzeitig aber in der nebenstehenden Tabelle diese Größen konkret aufführen.
Ebenso kommen Zweifel am Verständnis von Grundlagen bei den Autoren auf, wenn sie einerseits 'empfehlen', keine lokalen Arrays > 1KB zu verwenden und man stattdessen globale Variablen verwenden soll, andererseits weisen sie darauf hin, möglichst wenig globale Variablen zu verwenden;
was soll der Leser davon halten?

Auch weitere falsche Aussagen der Autoren zu den grundlegenden Datentypen reihen sich dicht an dicht:
- wchar_t ist als unsigned short definiert
- sizeof(float) ist immer 4 => ohne auf die für eine solche Pauschalaussgae zwingend notwendige Einschränkung __STDC_IEC_559__ ab C99 hinzuweisen
- bei Gleitkommakonstanten vergessen die Autoren auf Hex-Floats hinzuweisen
- Genauigkeit von double-Werte wird beschrieben wiederum mit konstanten Werten ohne DBL_DIGIT aus dem Standard zu nennen

Bei einfachsten C Grundlagen passieren den Autoren ebenso Unfälle, wie
- nicht explizit initialisierte lokale Variablen besitzen keinen definiterten Anfangswert => falsch, bei static schon
- void wird als Datentyp bezeichnet, was komplett sinnfrei ist; void ist kein Datentyp
- Variablen müssen zu Beginn eines Blocks definiert werden => falsch, ab C99 überall möglich
- wird eine Funktion ohne Returnwert deklariert, wird int angenommen => falsch, implicit int gilt nicht mehr ab C99
- Array-Dimension muss bei Definition konstant sein => falsch, nicht bei VLA ab C99

Auf Seite 53 passieren den Autoren gleich 4 grundlegende Fehler, was wiederum ihr Unverständnis offenlegt
- eine Funktion besitzt einen Datentyp -> falsch, Funktionen sind explizit im Standard von Daten abgegrenzt, der Returnwerttyp einer Funktion ist NICHT der Typ der Funktion
- Funktion ohne vorherige Deklaration ist möglich => falsch, ab C99 nicht mehr standardkonform
- double pow(); => wird explizit im Programm nochmals deklariert und überschreibt somit die Deklaration aus dem Header
- int printf(); => wird explizit im Programm nochmals deklariert -> ist undefiniertes Verhalten, da eine leere Parameterliste bei der Deklaration durch den Standard als unbekannte aber feste Anzahl von Parametern festgelegt wird, da printf aber eine variable Parameteranzahl besitzt, verstoßen die Autoren auch hier wieder gegen den Standard

Das "Neu"-Deklarieren von Standardfunktionen im eigenen Programm ist vollkommen überflüssig und führt zu Fehlern, was die Autoren offenbar auch wieder unwissentlich ignorieren und gehört sicherlich nicht in ein Lehrbuch.

Die konkreten Programmbeispiele der Autoren sind mit grundlegenden Fehlern durchsetzt:

- es wird behauptet, dass führende Leerzeichen vor einem scanf-Format eine Bedeutung haben => 'vergessen' zu erwähnen, dass dies nur für %c,%n,%[ gilt
- die ständige Verwendung von fflush(stdin); zum Löschen des Eingabepuffers => bedeutet undefiniertes Verhalten (UB)
- die Verwendung von 0,1,2 statt der Standardkonstanten SEEK_SET,SEEK_CUR,SEEK_END
- die Auflistung von feof als Makro, der Standard schreibt sie explizit als Funktion vor
- UB auch bei diesem Beispiel:

int ch;
scanf("%c",&ch);

- fehleranfällige Verwendung (Encoding-Abhängigkeiten zw. Editor,Compiler,Laufzeit NICHT beachtet) von deutschen Umlauten im Quelltext:

case 0x84: c = 'Ä';

- Unverständnis für Bibliotheksfunktion fgets bei:

char rest[501];
fgets(rest,500,stdin);

- die Autoren 'vergessen' auch mal einen Anweisungsblock:

if( line != NULL )
strcpy( line, buffer );
else
line = buffer;
no_memory = 1;

statt richtig:

if( line != NULL )
strcpy( line, buffer );
else
{
line = buffer;
no_memory = 1;
}

Vollens daneben greifen die Autoren, wenn sie versuchen, die toupper-Funktion nachzubilden mit:

toupper(c) (islower(c)?((c)-'a'+'A'):(c))

wobei sie explizit behaupten, dass diese Variante sowohl für ASCII wie auch für EBCDIC funktionieren würde; was komplett sinnfrei und naiv ist, denn diese fehlerhafte Implementierung ist gerade für EBCDIC falsch, in der gesamten Literatur zu diesem Thema der nicht kontinuierlichen Buchstabenfolge im Basic-Characterset wird genau EBCDIC als GEGENBeispiel angeführt, die diesen Fehler offenlegt.
Die Autoren haben überhaupt kein Verständnis vom standardisierten Characterset in C.

Ein Faible scheinen die Autoren für eigene 'Verbesserungen' an der Standardbibliothek zu haben ( toupper ist bereits im Standard vorhanden ), an anderer Stelle im Buch zeigen sie

#define BUFSIZ 512

BUFSIZ ist aber schon innerhalb von stdio.h definitiert gemäß Standard, diese 'Neudefinition' im eigenen Programm ist sehr gefährlich, kein C-Programmierer verändert etwas an den Standard-Headern, in ein Lehrbuch gehören solche Codeteile ganz gewiss nicht.

Den üblichen Anfänger-Fehler begehen die Autoren auch mit der Behauptung, dass Array-Namen in einen Zeiger auf das erste Array-Element zerfallen, ohne die im Standard explizit dokumentierten Ausnahmen zu nennen; das Thema Zeiger/Array ist das wichtigste Thema für einen Anfänger zum Verständnis für C, hier darf ein Lehrbuch keine Fehler machen.

Fazit:
Die Autoren sind mit ihrem selbstgesteckten Ziel, eine "vollständige" und auf dem "neuesten C11-Standard" basierende Einführung in die Sprache C zu präsentieren vollständig gescheitert.
Sie sind nicht in der Lage, die Spracherweiterungen von C99 und C11 zu benennen und dem Leser zu vermitteln, es werden lediglich die neuen Bibliotheksfunktionen aufgelistet und dies auch noch falsch:
die 250-seitige Auflistung von Funktionen beginnt mit dem Autoren-Hinweis: "Die mit ANSI gekennzeichneten Funktionen entsprechen dem ANSI-Standard von 1989..."
in der Folge sind aber sämtliche Funktionen, d.h. auch die, die nur in C99 oder C11 vorhanden sind, mit "ANSI" gekennzeichnet und somit allesamt falsch beschrieben; so etwas darf nicht vorkommen und das bei einem Lehrbuch mit so hohen eigenen Zielen und schon gar nicht in einer "3. Auflage 2013".
Die vielen Seiten zu veralteten Themen wie Windows-Oberflächenprogrammierung direkt mit WinAPI, die hardwarenahe Programmierung unter DOS mit Programmierung von EGA/VGA-Grafikkarten, near/far Zeigern, 64KB Speichersegmentierung sind bestenfalls Füllmaterial, mit dem ein Leser ganz gewiss keine "professionelle" Einführung in die Programmentwicklung mit C erhält.

Das Buch ist vollkommen unbrauchbar, kein Leser sollte nach diesem Buch versuchen, C zu erlernen.
Kommentar Kommentare (3) | Kommentar als Link | Neuester Kommentar: Jun 28, 2014 11:52 AM MEST


C von Kopf bis Fuß
C von Kopf bis Fuß
von David Griffiths
  Broschiert
Preis: EUR 49,90

7 von 12 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen inkompetent, grundsätzlich fehlerhaft, unbrauchbar, 28. Juli 2013
Rezension bezieht sich auf: C von Kopf bis Fuß (Broschiert)
Das Buch hat eindeutig seinen Anspruch verfehlt, Zitat: "bestes C Buch aller Zeiten" zu sein, wie es euphorisch auf dem Buchdeckel heißt; hierbei ist gleich mal zu bemerken, dass die im Buch genannten 'technischen Gutachter' auch gleichzeitig als Euphoriker auf dem Buchdeckel fungieren; verlagsexterne Aussagen waren wohl Mangelware.
Diese 'technischen Gutachter' Zitat: "...sichern, dass alles was wir hier behandelt haben, seine Richtigkeit hat".
Nach Lektüre des Buches haben aber für jeden halbwegs C-Kundigen sowohl Autoren wie auch die 'technischen Gutachter' einen Grundkurs in praxisnaher C-Programmierung dringend nötig.

Das Buch wendet sich an Programmierer, die schon einschlägige Erfahrungen haben, will aber ein reines Lehrbuch sein und nicht als Referenz betrachtet werden.
Neueste wissenschaftliche Erkenntnisse aus Metakognition und Lerntheorie sollen die Basis für die Gestaltung des Buches liefern; alles in allem ist auch dieser Ansatz gescheitert, neben vielen fachlichen Fehlern ist auch die Gestaltung des Buches eher unbrauchbar, krampfhaft den nun mal trockenen C-Lehrstoff mit vielen Bildern,Zeichnungen,Lückenquelltexten u.ä. anzureichern reicht nicht, wenn die zugrunde liegende fachliche Basis des Autorenpaares offensichtlich unzureichend ist.

Insgesamt ist die Lektüre des Buches aufgrund vielen verschiedenen Gestaltungmittel auf jeder Seite sehr unrythmisch zu lesen, ständig fragt man sich, was die jeweilige Gestaltungform denn nun bedeuten soll;
ebenfalls fällt auf, dass die Lücken-quelltexte nochmal anschließend komplett mit Lösung wiederholt werden, was auch zum offensichtlich angestrebten Füllungsgrad des Buches beiträgt damit der Leser auch wirklich nicht auf die Idee kommt, hier eine kurze Einführung in C vorzufinden;
Leser mit solchen Ansprüchen sind von den Autoren explizit nicht erwünscht, ebenso wie solche
Zitat: "würden sich lieber von 15 kreischenden Affen die Zehennägel ziehen lassen als einmal etwas Neues auszuprobieren".

Wenn das alles ist, was das Autorenpaar inkl. zweier technischer Gutachter anbieten kann, darf man getrost auch die anderen genannten Fachbücher der Autoren vergessen:
Zitat: "Er kann in über 10 Sprachen programmieren, schreibt aber nur in einer."; hier kann definitiv aber nicht C gemeint sein, vielleicht ja Englisch.

Jemand der in über 10 Sprachen programmieren kann, kann naturgemäß nur wenig Praxiserfahrung in jeder dieser Sprachen besitzen, so ist es auch beim
Autorenpaar; schon zu Beginn beschreiben sie C als 'komplexe' Programmiersprache, was sie eindeutig aber gerade nicht ist; es war bekanntlich
Anliegen bei C, ein kleine, überschaubare und somit leicht portierbare Sprache zu erstellen und eben gerade keine komplexe.
Die Autoren haben das Grundanliegen von C nicht verstanden.

Reichlich eigenwillig arbeitet auch der Übersetzer, wenn er das Stringendezeichen '\0' eigenwillig mit 'Wächterzeichen' übersetzt.
Rätsel geben ebenfalls die durchgängig mit Copyright 2014 gekennzeichneten Quelltexte auf.

Das Buch enthält tatsächlich keinerlei tabellarische Übersichten über Sprachumfang und Standardbibliothek, die Operator-Vorrangtabelle
und eine (sortierte) Übersicht über die Bibliotheksfunktionen gehören in JEDES C-Buch, egal ob nun 'wissenschaftlich' oder nicht.

Das Buch konzentriert sich ausschließlich am Compiler gcc für Unix/Mac/Windows; IDE werden nicht verwendet oder vorgestellt.
Es ist wenig motivierend für einen C Einsteiger, sich noch mit Entwicklungsumgebungen auseinanderzusetzen oder sich gar direkt mit Editor
und Compileroptionen auf Kommandozeilenebene herumzuschlagen.

Nach 36 einführenden Seiten mit den üblichen Danksagungen und Eigenlob (immerhin ist eine Widmung an D.M.Ritchie dabei) geht es dann auch schon los.

Und mit den ersten Fehlern,
- wiederholt wird statt einfach 'make programm' nur 'gcc programm.c -o programm' gezeigt, die einfache make-Variante ohne Makefile
kommt sogar in dem Extrakapitel zu make nicht vor
Auch behaupten die Autoren, der Compiler erstelle das Programm, obwohl sie sich dann selbst widersprichen indem sie feststellen, dass der Compiler
lediglich die Objekt-Dateien erstellt; hier fehlt die Aussage zum Linker, der das Programm endgültig aus Objekt- und Bibliotheksdateien erzeugt.

Auch die ersten konkreten Codezeilen zeigen die Praxisferne des Autorenteams, indem sie bei
char ex[20];
scanf("%19s",ex);
- vergessen, auf den Abbruch von scanf beim 1. Whitespace hinzuweisen (erst viel später im Buch weisen die Autoren darauf hin, s.u.)
- und den return-Wert von scanf nicht auswerten (das passiert dann erst viel später im Buch bei fscanf)
Dies ist auch wieder ein Inkonsequenz: es gibt keine klare Linie, die die Autoren bei der Verwendung von Funktionen zeigen und auch über das gesamte Buch hinweg einhalten; im vorletzten Kapitel sagen sie dann, man solle den Funktions-Returnwert beim Aufruf externer Systemfunktionen (execl,...) verwenden; d.h. für andere also nicht.
Für ein (selbsternanntes) Lehrbuch sind solche 'verzögerten' Informationen an den Leser absolut nicht zu tolerieren.
Überhaupt scheitern die Autoren auch bei anderen Gelegenheiten am simplen Einlesen von Strings.
So zeigen sie wiederholt

char name[80];
fgets(name,sizeof(name),stdin);

und arbeiten dann mit diesem String weiter ohne dem Leser zu erklären, dass zwar hier gegenüber scanf nicht beim 1. Whitespace abgebrochen wird dafür aber das endende '\n' mit enthalten ist (meistens), d.h. der String enthält also "Max Mustermann\n" und nicht wie ein C-Einsteiger erwarten würde "Max Mustermann". Dies hätten die Autoren selbst erkennen können, wenn sie ihre eigenen Aussagen im Buch verstanden hätten, wie unten erwähnt, beschreiben
sie "fgets hängt immer '\n' an"; die Übersicht der Autoren über ihr eigenes Werk ist also ebenso nicht gegeben.
Das sind alles Basics, die einem mit der täglichen C-Praxis vertrauten Entwickler bekannt sind, wozu die Autoren wie auch bei ihren vielen anderen
Fehlern, definitiv nicht Anlaß geben.

Reichlich naiv sind auch die wenigen Antworten zum allgemeinen Programmaufbau/design:
"Woher weiß ich, welchen Standard mein Compiler unterstützt?" -> "Schauen Sie in der Compilerdoku nach"
anstatt hier konkret die standardisierten Funktionalitäten zu zeigen
(__STDC__,__STDC_VERSION__)
Diese Verständnislosigkeit der Autoren zu den Standards führt dann dazu, dass sie nicht dokumentieren, welchen C-Standard sie selbst in diesem
Buch anwenden (C89/C99/C11); wahrscheinlich ist es aber C99, da Variablendefinitionen mitten im Anweisungsblock vorkommen; noch wahrscheinlicher
ist aber, dass die Autoren überhaupt keinen der Standards strikt befolgen und den gcc-Default gnu99 (erweitertes C99 plus gcc-Erweiterungen) benutzen.
In der Auflistung der wichtigen gcc-Optionen fehlen dann auch (konsequenterweise) die entsprechenden standardkonformen Optionen
-pedantic bzw. -pedantic-errors, die eine strikte Verwendung des jeweiligen Standards absichern (-std=c89/c99/c11).

Gängige Fachbegriffe werden nicht vermittelt, bei
"was passiert wenn sie versuchen, ein Element eines Stringliterals zu ändern?"
wird der Leser auf die Programmausgabe "Bus-Error" fokussiert, anstatt genau hier den passenden Fachbegriff undefiniertes Verhalten/undefined behavior (UB) einzuführen.

Die Werte true/false (ab C99) werden vorgestellt ohne deren Typ (_Bool) zu nennen, sowas ist mehr als ein Flüchtigkeitsfehler für ein Lehrbuch mit so hohen eigenen Ansprüchen.

Die ab C99 mögliche for-interne Variablendefinition ( for(int i=0;..;..) ) vergessen die Autoren ebenso zu zeigen, obwohl sie sonst ausschließlich C99 Code verwenden.

Praxisferne beweisen sie weiterhin mit
- in void-Funktionen ist return sinnlos => sehr wohl sinnvoll, z.B. zum Beenden der void-Funktion aus Schleifen heraus
- fgets hängt immer '\n' an => falsch, nicht immer
- scanf liest nur bis zum 1. Leerzeichen => falsch und ungenau, es muss 1. Whitespace heißen
- long double vergessen bei Vorstellung der Fließkommadatentypen
- LNG_MAX/LNG_MIN statt richtig LONG_MAX/LONG_MIN
- Liste reservierter Wörter falsch dargestellt mit 'entry'
- max. gleichzeitig geöffnete Datenströme falsch mit Absolutzahl genannt => richtig ist FOPEN_MAX
- Behauptung, strdup wäre eine Standardfunktion => falsch, ist keine
- Behauptung, Zeiger wären im 64Bit-Betriebssystem 64 Bit lang, bei 32Bit 32 Bit lang => falsch, die Bitlänge von Datentypen hängt vom Compilat ab und NICHT
von der Laufzeitumgebung; bspw. sind Zeiger in 32-Bit compilierten Programmen nach wie vor 32 Bit lang (meistens), auch wenn sie unter einem 64Bit Betriebsystem laufen
- die Behauptung, switch/case vergleiche nur Einzelwerte => da die Autoren den gcc als das Mittel ihrer Wahl auserkoren haben, fehlt hier der Hinweis, dass
der gcc case ranges unterstützt (als spezifische Compilererweiterung), also 'case 1 ... 99:' möglich ist
- die Behauptung, dass keine Binärliterale möglich seien da die Autoren den gcc als das Mittel ihrer Wahl auserkoren haben, fehlt hier der Hinweis, dass
der gcc Bereiche verarbeiten kann (0b01010101)
Die Autoren kennen also nicht nur die C-Standards nicht und verwechseln hierbei ständig sondern sie kennen auch die gcc-Features offensichtlich nicht, d.h.
sie haben auch den gcc-Featuremodus (gnu99) gegenüber dem gcc-strict Modus nicht verstanden
- ständige Verwechslung von Deklaration mit Definition
- Datentyp der Rückgabe von sizeof ist implementierungsabhängig => falsch, ist immer size_t
Prinzipielle Verständnisschwierigkeiten bei size_t offenbaren die Autoren auch weiterhin:
- sizeof wird während der Compilierung berechnet => falsch, beim von den Autoren favorisierten C99 gibt es die Ausnahme VLA
- weiterhin machen sie auch noch den printf-Fehler mit %z => richtig ist %zu
bzw. sie benutzen sogar einen Cast printf("%u",(unsigned int)sizeof(wert));
Cast zeigen bis auf ganz wenige Ausnahmen (die die Autoren nicht nennen/kennen) immer an, dass das Programmdesign nicht stimmt, und gehört ganz gewiss nicht in ein Lehrbuch.
Ungeniert casten die Autoren auch mal ein const weg, sowas geht GAR NICHT, schon GAR NICHT in einem Lehrbuch:

int cmp(const void *a,const void *b)
{
int x=*(int*)a;
int y=*(int*)b;
return a - b;
}
Bei dieser Callback-Funktion für qsort zeigt sich auch wieder das grundlegende Unverständnis der Autoren zu C und ihre Praxisferne, denn neben dem Wegcasten
von const begehen sie hier 2 weitere Anfänger-Fehler:
- liegen a und/oder b an den int-Grenzen, liefert die Funktion ein falsches Ergebnis (wegen int-Über/Unterlauf)
- ein signed int-Über/Unterlauf ist auch gleichzeitig UB ( den Autoren aber wohl unbekannt, wie schon erwähnt, kommt dieses wichtige Kriterium bei den
Autoren nie vor, ein weiteres Index für deren Inkompetenz und Praxisferne )

Beim wichtigen Thema Pointer und Arrays scheitern die Autoren auch wieder kläglich, indem sie den weit verbreiteten Anfängerglauben aufsitzen und behaupten,
"Im Prinzip arbeitet eine Array-Variable wie ein Zeiger"; "im Prinzip" heißt ja wohl, dass es Ausnahmen gibt, welche, bleiben die Autoren schuldig.
"Adresse einer Array-Variablen ist die Array-Variable selbst" d.h. array == &array ; was absoluter Unsinn ist, aus mehreren Gründen, die alle den
Autoren nicht bekannt sind, sonst würden sie diese sinnfreie Aussage nicht machen.
Verständnis über Pointer ist DIE essentielle Grundlage bei C, die Autoren haben dieses Verständnis nachweislich eindeutig nicht.

Ein ganzes Kapitel verwenden die Autoren auf Funktionen, die angeblich zuvor nicht deklariert werden brauchen, aber trotzdem verwendet werden dürfen.
Der C99 Standard schreibt eindeutig vor, dass dies NICHT (mehr) erlaubt ist, alle Versuche der Autoren, in dem Kapitel aufzuzeigen, wie der Compiler in diesem Fall vorgeht und was zu beachten ist, sind also standardinkonform und somit falsch, gehören nicht in ein Lehrbuch usw...
Zumal sie bei ihren 'Erklärungen' auch nur auf die Promotion des Rückgabewertes solcher Funktionen eingehen; die viel wichtigere weil häufiger (unter C89) angewendete default argument promotion erwähnen, erklären und zeigen sie nicht.
Das ganze Kapitel ist unbrauchbar, dabei hatten die Autoren doch zu Beginn des Buches versprochen, jeweils darauf hinzuweisen, wenn Features bestimmter C-Standards (C89/C99/C11) verwendet werden. Es spricht vieles dafür, dass die Autoren aufgrund ihres eigenen fehlenden Standard-Wissens den Überblick in ihrem eigenen Werk verloren haben, wenn sie ihn denn jemals besessen haben.

Im Kapitel über Multithreading empfehlen sie für die Windows-Plattform cygwin, ohne den Leser auf win32-pthreads hinzuweisen, die die POSIX pthreads nahezu identisch abbilden, der Leser kommt damit also ohne die aufwändige Abhängigkeit von cygwin aus und kann die Quelltexte direkt anwenden.

Beim Thema Datenstrukturen werden ausschließlich die praxisuntauglichen verketteten Listen behandelt,
Beispiele zu den aufgelisteten Maps findet der Leser nicht.

Allgemeine Hinweise zum Programmdesign sucht man im Buch vergebens, lapidare Empfehlungen wie
'verwenden sie globale Variablen möglichst wenig' => statt (verwenden sie nie globale Variablen)
tragen ebenfalls wenig zur Praxistauglichkeit der vorgestellten Quelltexte (welche häufig davon unnötig Gebrauch machen) bei.
Ebenfalls fehlen Hinweise zum Umgang mit const/volatile/inline und zu assert für die Absicherung von Bedingungen; alles bekannte Hilfsmittel, die bei einer praxisorientierten C-Programmierung bzw. beim Design unumgänglich sind, und frühzeitig (schon zur Compilezeit) auf Designfehler hinweisen.

Fazit:
Die Autoren haben ein unbrauchbares Buch mit vielen grundsätzlichen Fehlern abgeliefert, welches utopisch weit vom selbstgesteckten Ziel "bestes C-Buch aller Zeiten" entfernt ist. Sie und ihre 'technischen Gutachter' haben kläglich versagt beim Versuch, dem Leser einen fundierten und belastbaren Einstieg in C zu ermöglichen.
Die Autoren verstecken ihr mangelndes Grundlagenwissen, ihr laienhaftes Verständnis vom Programmdesign und ihr nachweislich praxisuntaugliches Coding hinter selbsternannten 'wissenschaftlichen Lernmethoden'.
Ein marodes Fundament lässt sich von einer blendenden Fassade bestenfalls kaschieren und wird bei jeder Belastung zusammenbrechen.
626 Seiten geballte Unsicherheit bei Grundlagen+Coding sind auch mit 'wissenschaftlichem' Deckmantel niemandem zu empfehlen.


C programmieren: Einstieg und Praxis
C programmieren: Einstieg und Praxis
von Jürgen Wolf
  Taschenbuch

2 von 5 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen inkompetent, fehlerhaft, niemandem zu empfehlen, 21. Juli 2013
Das Buch ist eine einzige didaktische Katastrophe.
Neben den vielen grundsätzlichen Fehlern, die der Autor dem Leser in Erklärung und Code
zumutet, ist auch der Lerneffekt gleich Null; das Lesen des Buches ist sogar schädlich,
denn der Leser muss vieles vergessen und neu richtig lernen, will er C wirklich einsetzen.

Die Didaktik bleibt wie gesagt, völlig außen vor.
Zunächst zeigt der Autor ein Bild zum Ablauf der Programmerstellung ohne Preprozessor,
wenige Seiten später dann plötzlich ein nahezu identisches Bild mit Preprozessor.
Nachdem sich also der Leser das erste Bild angeschaut hat, kann er es gleich wieder vergessen,
und sich das zweite merken. (wobei er natürlich nicht wissen kann, welches korrekt ist).

Ein Leser ohne Vorkenntnisse (wie vom Autor genannt: "sie müssen nur Tastaur+Maus bedienen können")
ist mit dieser Art des "Lernens" komplett überfordert.
Dasselbe gilt für die Einführung des Begriffes "Funktion": hier schreibt Autor z.B.
"... die Parameter argv,argc zwischen den Klammern der main-Funktion..." und erklärt gar nicht erst,
was eine Funktion ist; der Leser erfährt dies erst ca. 120 Seiten später und ohne vorher darauf hingewiesen zu werden.
Der Leser bleibt also mit seinen verständlichen Fragen zur Begriffsdefinition allein.
Was ist eigentlich so schwierig daran, bei der ersten Verwendung eines Fachbegriffes in einem Anfängerlehrbuch
auch sofort die Erklärung zu liefern? Sicher nicht viel, aber schwierig für den Autor, solch triviale und selbstverständliche Lernhilfen umzusetzen.

Auch die C-Standards muss sich der Leser über das ganze Buch verteilt zusammensuchen (C89/C99/C11).
Wozu der Standard da ist, was der Standard normt, erklärt der Autor nicht vollständig und schon gar nicht zusammenhängend und somit falsch.

Ebenfalls über das ganze Buch hinweg verwechselt der Autor den Begriff Deklaration mit Definition.
... 'bei einer Deklaration wird ein Bereich im Arbeitsspeicher reserviert' ... (falsch, eine Deklaration reserviert niemals Speicher, nur eine
Definition tut das)

int i;
ist beim Autor eine Deklaration (ca. 95% falsch), manchmal aber auch (5% richtig) eine Definition

Bei Vorstellung von z.B. sizeof(),strlen() 'verzichtet' der Autor darauf, den wichtigen Datentyp size_t einzuführen.
size_t wird im ganzen Buch nicht erklärt.

Schwierigkeiten hat der Autor auch, eine geeignete Namenskonvention in seinen Beispielen zu finden:
char pass[];
char Passwort[];
mal Groß-/Kleinschreibung; auch hier hat der Autor den Überblick über sein eigenes 'Werk' verloren (wenn er es denn jemals besessen hat)

Auch komplett falsche Aussagen reihen sich in diesem Buch dicht an dicht:

- der int Wertebereich wird falsch sowohl im Klappentext wie auch im Buchtext falsch mit -32768 -> 32767 angegeben (richtig ist ein Mindestbereich von -32767 -> 32767)
- am Ende von main geschieht immer ein implizites "return 0;" (falsch: nicht in C89)
- mal wird "%lf", mal "%f" für double-Werte bei printf genannt (ohne Erläuterung, was C99 dazu definiert)
- printf+scanf haben dieselben Formatbezeichner (falsch: sie haben unterschiedliche)
- das Hochkommazeichen <'> innerhalb von Stringkonstanten benötigt \-Kennzeichner (falsch: "'" ist korrekt)
- fflush(stdin); (naive Vorstellungswelt des Autors, wenn er schreibt: '...mit gcc/clang funktioniert dies schon nicht mehr so zuverlässig...')
(auch hierbei hat der Autor nicht verstanden, was der C-Standard hierfür vorschreibt)
- fgets hängt immer ein '\n' an (wobei der Autor diese Aussage sogar 2x mal macht (S.189+S.192), damit der Leser diesen Unsinn auch wirklich begreift)
- 'ein C-Programm ist ohne main() ausführbar'
- void funktion(int arrayname[]); 'ein Indexwert darf nicht angegeben werden' (falsch: darf sehr wohl angegeben werden, wird hierbei immer ignoriert)
- scanf liest nur bis zum ersten Whitespace-Zeichen
- scanf prüft nicht die Anzahl der eingegebenen Zeichen (der Autor widerspricht sich hier inner weniger Sätze selbst, indem er scanf("%99s") zeigt,
wo diese zuvor noch 'unmögliche' Zeichenprüfung abläuft
- 'in der Praxis ist es möglich, ein Array dynamisch zu machen' (falsch: ein Array besitzt immer genau die bei der Definition festgelegte Größe)

Schon bei einfachstem Beispielcode (nach dem üblichen "hello world" Niveau) scheitert der Autor kläglich:
- statt printf("\n") kann man lt. Autor auch printf("%c",10); verwenden (falsch: scheitert unter DOS/Windows/Mac)

beim Versuch, scanf zu erklären:

char zeichen;
scanf("%[^x]",&zeichen);

Dies bedeutet undefiniertes Verhalten (UB), gehört definitiv nicht in ein Lehrbuch eines "Bestseller"-Autors und
passiert nur Leuten, die die Grundsätze prinzipiell NICHT verstanden haben
(es wird undefinierter Speicherbereich beschrieben, und das geht wie gesagt, GAR NICHT)
Weiterhin erklärt der Autor niemals im Buch die Return-Werte von scanf/sscanf - ein wichtige Information über den Erfolg des Funktionsaufrufes

Die sinnfreie Verwendung von
strncat(str," ",1);
statt
strcat(str," ");

zieht sich ebenso über das ganze Buch hin wie sinnfreie Verwendung von strncpy statt strcpy
strncpy(str,"Kaffeedose",sizeof("Kaffeedose")+1);
statt
strcpy(str,"Kaffeedose");

Der Auto suggeriert hier eine falsche 'Sicherheit' von strncpy ggü. strcpy, indem er das evtl. Schreiben in undefinierten Speicher eintauscht gegen
die evtl. fehlende String-Ende-Kennung durch strncpy; der Code verschleiert/verzögert also Fehler nur, was eine Fehlersuche immer erschwert.

Schon bei einfachsten kurzen Beispielenn verliert der Autor wie gesagt den Überblick:

FILE *f;
f=fopen("c:/...","r");
if(f==NULL)
perror("Fehler");
else
printf("Ok");
fclose(f);

Hier liegt schon wieder UB vor ( bei fclose und f==NULL ).

Auch beim ersten praktischen Versuch mit konkreten Dateien zu arbeiten, scheitert der Autor kläglich, wenn er zeigt:

char file_name[255];
fgets(file_name,sizeof(file_name),stdin);
f=fopen(file_name,"r");

Hier wird der Code sehr wahrscheinlich immer scheitern, (außer file_name ist genau 254 Zeichen lang),
da das durch fgets vorhandene endende '\n' üblicherweise nahezu ausgeschlossen bei existierenden Dateinamen ist.

Im Beispielprogramm zur Lagerverwaltung versucht der Autor, ein struct-Array aus einer Datei in eine verkettete Liste zu lesen.
Leider gibt es auch hier sinnfreie Erklärungen wie:
- bei der Zuweisung einer struct-Variablen könnte der Compiler Fehler machen... (der Einzige, der hier Fehler macht, ist der Autor selbst)
Stattdessen empfiehlt und zeigt der Autor doch tatsächlich die einzelne, elementweise Zuweisung bei struct.
Falls sich etwas an der struct-Definition ändern, muss also der Code umgebaut werden; soviel zur Praxiskenntnis des Autors.
Weiterhin verwendet der Autor beim Lesen der struct-Einträge aus der Datei naiv eine zusätzliche temp. Variable und ist dadurch natürlich genötigt,
diese struct-Zuweisung überhaupt erst durchzuführen, anstatt direkt von fread in das Listenelement zu schreiben (was den einzelnen Elementzugriff
überflüssig machen würde).
Ebenso vergisst der Autor ein abschließendes fclose() bei all seinen Beispielen zu o.g. Lagerverwaltungsprogramm.

Die im Anhang aufgeführte Rangtabelle der Operatoren ist falsch (++ und -- gehören nicht in die erste Priorität), richtig abschreiben kann der Autor auch nicht.

Fazit:
Das Buch reiht sich nahtlos in die Reihe untauglicher Versuche des Autors selbst und anderer deutsche Fachbuchautoren ein, Anfängern+Fortgeschrittenen einen ersten Überlick über die Programmiersprache C zu geben.
Dieses 'Werk' ist niemandem zu empfehlen, es sei denn, der Leser möchte bei jeder Aussage und Beispielcode selbst herausfinden, ob sie korrekt ist oder nicht.
Kommentar Kommentar (1) | Kommentar als Link | Neuester Kommentar: Nov 27, 2013 9:45 AM CET


C - Einführung und professionelle Anwendung. IT-Studienausgabe
C - Einführung und professionelle Anwendung. IT-Studienausgabe
von Ulla Kirch
  Gebundene Ausgabe

6 von 6 Kunden fanden die folgende Rezension hilfreich
2.0 von 5 Sternen nur sehr, sehr eingeschränkt zu empfehlen, 25. November 2012
Das Werk des teilweise habilitierten Autorenpaars wird dem Titel eindeutig nicht gerecht,
professionelle Anwendungen kann niemand allein mit diesem Buchwissen schreiben.
Maximal sind Programme auf "hello world"-Niveau als (Windows)GUI-Anwendungen denkbar.
Außerdem enthält das Buch eine Reihe von Fehlern, die dem Anspruch des Buches nach C99-Konformität
und auch der langen Historie dieses Werkes und seiner Autoren eindeutig NICHT gerecht werden.
Das Buch ist nur mit sehr großen Einschränkungen überhaupt zu empfehlen.

Das Buch richtet sich lt. Autoren an Anfänger und Fortgeschrittene, die das Schreiben professioneller C-Programme erlernen wollen.
Dieses Ziel erreicht dieses Buch eindeutig nicht, professionelle Programme schreibt niemand nach Lektüre eines Buches, schon gar nicht dieses Buches, hier erwecken die Autoren (wohl aus Marketinggründen) einen falschen Anschein.

Zu Beginn schon äußert sich das Unverständnis der Autoren bei der ausschließlichen Verwendung von "ANSI C99", was der C-Historie eindeutig nicht gerecht wird. Das ANSI Komitee hat erst 2000 den ISO C-Standard von 1999 übernommen, also wenn dann wäre ANSI C2000 korrekt, besser noch wäre die allseits verbreitete Formulierung C99 oder ISO C99.

Auch die durchgängig merkwürdige Schreibweise von Lay-out statt Layout gibt dem Leser Rätsel auf.

- "C ist an der Architektur der heutigen Rechner orientiert" -> kann niemals der Fall sein, denn zu Entstehungszeit von C 1972 konnte niemand die "heutigen" Rechnerarchitekturen kennen
- "hardwareabhängige Bestandteile von C wurden reduziert" -> Unsinn, da der C-Sprachstandard gerade keine Hardware und deren Eigenheiten kennt oder voraussetzt, im Gegenteil, es ist gerade ein Vorteil von C, aufgrund des geringen Sprach- und Bibliotheksumfanges sehr portabel und plattformunabhängig zu sein

Die Autoren weisen zwar darauf hin, dass sich mit C99 eine Erweiterung des bisherigen (C89)-Standards ergeben hat und sie jeweils in dem Buch darauf hinweisen werden, falls diese Neuerungen verwendet werden, scheitern aber schon beim 1.Beispiel daran ( Einzeilenkommentare "//" gibt es erst ab C99, worauf die Autoren nicht hinweisen )

Auch 'verzichten' die Autoren vollständig auf wichtige Fachbegriffe aus dem C-Standard, wie undefiniertes/unspezifiziertes/implementierungsabhängiges Verhalten.
Wertebereiche der Integer- und Gleitkomma-Basistypen werden falsch angegeben, diese sind gemäß C-Standard implementierungs- d.h. compilerabhängig und nicht fest, wie die Autoren schreiben.

Wenig Detailkenntnis offenbaren die Autoren auch bei der Behauptung, "char hat 8 Bit", -> falsch, gemäß Standard hat char genau CHAR_BIT Bits, und CHAR_BIT kann dabei >= 8 sein.
- "wchar_t = unsigned short" -> ist ebenso falsch weil implementierungsabhängig
- "int-Länge entspricht der Bit-Länge eines Maschinenregisters" -> auch hier wieder falsch, auch das ist wieder implementierungsabhängig und eben NICHT hardwareabhängig, z.B. erzeugt ein 32-Bit Compilersystem üblicherweise int-Werte mit 32-Bit Länge, die auf einem 64-Bit Rechner nach wie vor 32-Bit bleiben
- "sizeof(float) == 4" ist ebenso falsch, da der C-Standard den IEEE-754 Standard zur Fließkommabehandlung nicht definiert, und somit die 32-Bit floats aus IEEE nicht für C-Compiler gelten müssen
- den wichtigen Datentyp 'size_t' (z.B. als Rückgabewert von sizeof,strlen,...) 'vermeiden' die Autoren im ganzen Buch zu nennen
- "bei externen Bezeichnern sind die ersten 8 Zeichen signifikant" -> falsch, C89 sieht hier 6 vor, C99 hingegen 31
- "nicht initialisierte lokale Variablen haben undefinierten Anfangswert" -> falsch, lokale statische Variablen haben 0 als (impliziten) Initialwert
- printf("%d",sizeof(x)); verwendet, was UB (undefined behavior) bedeutet, ohne Hinweis auf C99, wo für size_t das Format "%zu" eingeführt wurde
- "Funktionsaufruf ohne vorige Deklaration -> Rückgabetyp int wird angenommen": ohne Hinweis, dass mit C99 solcher Aufruf nicht mehr konform ist
- "die Standardheader iso646.h und wchar.h wurden mit C99 eingeführt" -> falsch, zusammen mit wctype.h schon in C95

Bei konkreten Beispielcodes offenbaren sich dann weitere Unverständnisse der Autoren:
- #include <stdlib.h>
void srand(unsigned seed);
-> die in diesem Beispiel explizit erneut deklarierte Standardfunktion ist schlecht, prinzipiell sollte man nie irgendwas aus den Standardheadern 'verbessern' oder gar ändern
- fflush(stdin) wird häufig in Beispielen verwendet und explizit nochmal ausführlich erklärt, dass man so den Eingabepuffer löschen kann -> falsch, UB
- int ch;
scanf("%c",&ch);
-> falsch, Zeiger auf char erwartet, Zeiger auf int übergeben, die müssen gemäß Standard NICHT kompatibel sein -> UB
- Verwendung von "void main()" -> nicht standardkonform
- ".. unter den Betriebssystemen WINDOWS/DOS und UNIX kann ein dritter Parameter in main verwendet werden..."
int main(int argc,char**argv,char**envp)
Das ist kein C-Standard, sondern implementierungs- also compilerabhängig und NICHT BS-abhängig.
- (int*)malloc -> unnötiger Cast in C
- free(ptr) "...MUSS zuvor mit malloc/calloc/realloc reserviert worden sein..." : kein Hinweis, dass hier auch NULL möglich ist
- Verwendung von gets (zwar mit Hinweis, dass fgets besser ist, besser wäre dann aber gleich die Verwendung von fgets im Beispiel)
- while( scanf("%1[JNjn]",a)==0 )
fflush(stdin);
hier sind gleich 3 Fehler vorhanden
- fflush auf stdin ist UB
- liefert scanf hier EOF (d.h. -1), dann würde das Programm dies als gültige Eingabe interpretieren (und falsch weiterarbeiten)
- nach Ende von while ist der Einpuffer ungelöscht
- der übliche Fehler bei Callback-Funktion für das Sortieren von int mit qsort wird gemacht:
*(int*)a - *(int*)b;
was bei Werten in der Nähe von den int-Grenzen zu Fehlern führt
- fcloseall beschrieben: keine Standardfunktion
- exit(); und return aus main beschrieben ohne EXIT_SUCCESS/EXIT_FAILURE aus dem Standard zu nennen
- im Beispiel zu einer String-Ersetzungsfunktion void replace_all(char *old,char *new)
hätte sich gut eine Erklärung zum Unterschied zw.
char s[]="hello world";
und
char *s="hello world";
angeboten
- scanf("%80s", stringvar); ohne Hinweis auf den Abbruch beim 1. Whitespace dieser Variante
- NULL-Zeiger: "...ist als 0 definiert..." -> falsch, der Standard definiert NULL als Integerkonstante mit Wert 0, d.h. neben 0 wäre auch 0L oder (void*)0 denkbar; dies ist dem jeweiligen Compilerhersteller überlassen, also implementierungsabhängig und nicht etwa fest vorgegeben, wie hier beschrieben
- "Die Zeigerversion ist in der Regel der Indexversion vorzuziehen..." wenig verständlich in der heutigen Zeit der hochoptimierden Compiler ist das Compilat häufig sehr ähnlich wenn nicht gar identisch; lesbarer und einfacher ist die Arrayvariante, da kein extra Zeiger zum Iterieren definiert werden muss sondern ausschließlich das Array selbst referenziert wird
- durchgängige Verwendung von Vektor statt Array; schlechte Abgrenzung zum vector in C++, was dort etwas ganz anderes bedeutet ( die Autoren schreiben auch Bücher über C++ und hätten das erkennen müssen )
- unsinnige Empfehlung: "Vektoren mit größerem Speicherbereich sollten global definiert werden"; ohne Hinweis auf dynamischen Speicher, der einige Kapitel später vorgestellt wird; hier offenbart sich der mangelnde Überblick der Autoren über ihr eigenes Werk
- Vektorname ist identisch zur Adresse des 1.Elements -> ohne die im Standard definierten Ausnahmen zu nennen;
wenn das so wäre, wäre z.B. auch
int array[10];
array = NULL;
möglich, denn wenn array IMMER ein Zeiger wäre, würde hier kein Fehler auftreten, array wäre einfach ein Zeiger und als Lvalue möglich
- Entscheidungsoperator "?:" wird im Operator-Kapitel nicht genannt (findet man erst 2 Kapitel weiter in "Kontrollstrukturen", wo er nicht hingehört, da Operator und keine Kontrollstruktur )

Bei "Typ ganzzahliger Konstanten" ohne Suffix für Dezimalkonstanten beschreiben die Autoren nur "int, long, long long" ohne Hinweis, dass dies nur C99 relevant ist und C89 etwas anderes vorschreibt: 'int, long, unsigned long'.

Im gesamten Buch fehlt eine Übersicht über die Vorrangregeln aller Operatoren, der Leser muss sie einzeln in den Kapitel suchen (arithmetische,Vergleich,Bit,...).
Bei der Vorstellung der logischen Operatoren fehlt der Hinweis auf deren short-circuiting.
"In einem DOS-Editor (wie z.B. EDIT)..." legt den Schluss nahe, dass dieses Buch schon eine lange Historie hat, wahrscheinlich schon seit Beginn 90er ("C für PCs", dort wahrscheinlich mit noch mehr Fehlern als in diesem (neuesten) Buch).
Das Kapitel 25 "Hardware-nahe Programmierung unter DOS" mit Interrupts, 16-Bit Speichersegmentierung, 1MB Adressraum, EGA/VGA Bildschirmspeicher lässt ebenso den Schluss zu, dass hier völlig veraltete Beispiele gewählt wurden, die nichts mehr mit aktuellen "professionellen" Anwendungen zu tun haben.
Das trifft auch auf die Kapitel zur Windows-GUI-Programmierung zu, in denen die ebenfalls veralteten Funktionsaufrufe der Windows-API zur Window/GDI/Font... Programmierung relativ ausführlich vorgestellt werden.

Einen wesentlichen Umfang im Buch nimmt die Beschreibung der Bibliotheksfunktionen ein, immerhin fast 300 S. von 858 S. werden hiervon belegt.
Immerhin ist diese Referenz alphabetisch aufgebaut, C99 Hinweise liegen vor und manchmal auch ein Codebeispiel.
Wer eine umfangreiche, deutschsprachige Referenz über die C-Bibliothek sucht, kann diese hier finden.

Dieses stark Windows-lastige Werk genügt keinesfalls zum Aufbau von professionellem C-Wissen, die Autoren versprechen hier etwas Falsches.
Die teilweise veralteten Beispiele, die nicht vorhandene Operator-Vorrangtabelle, das ständige UB "fflush(stdin)" führen dazu, dass dieses Buch für Einsteiger und Fortgeschrittene nur sehr, sehr eingeschränkt zu empfehlen ist.
Von einem teilweise habilitierten Autorenpaar kann man in einer '2. aktualisierten und erweiterten Auflage 2007' und bei der langjährigen Historie des Buches bis in die 90er Jahre hinein erwarten, dass keine Anfängerfehler und UB mehr vorkommen.
Kommentar Kommentare (5) | Kommentar als Link | Neuester Kommentar: Feb 4, 2014 2:08 PM CET


C - kurz & gut
C - kurz & gut
von Peter Prinz
  Taschenbuch
Preis: EUR 8,00

5 von 6 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen einigermaßen brauchbar, 3. November 2012
Rezension bezieht sich auf: C - kurz & gut (Taschenbuch)
Das teilweise habilitierte Autorenpaar möchte mit diesem kleinen Taschenbuch (120 S.) die Programmiersprache C kompakt beschreiben, inkl. der Standardbibliothek.
Wegen einiger Fehler und mangelnder Sorgfalt ist es nur eingeschränkt empfehlenswert und nur für bereits fortgeschrittene Programmierer (in anderen Sprachen).
Als Lehrbuch ist es aufgrund des geringen Umfanges und der wenigen Beispielcodes nicht zu empfehlen, ebenso nicht als Referenz zur Standardbibliothek aufgrund des kleinen Buchformates und der hierdurch bedingten mühsamen Suche.

Die Autoren bezeichnen den C-Standard meistens als ANSI C99, was falsch ist, da der zum Zeitpunkt der Drucklegung des Buches aktuelle Sprachstandard ISO/IEC 9899:1999 war, der von ANSI erst 2000 übernommen wurde (von ISO), korrekt wäre also ANSI C 2000 gewesen oder wie allgemein üblich C99 (ohne ANSI) oder ISO C99 oder einfach ANSI C (wie es die Autoren auch manchmal selbst verwenden).

Die Autoren kommen zu Beginn schwer in Gang:
"C wurde in 70er Jahren entwickelt",
... "ist portable Sprache, die sich an der Architektur der heutigen Rechner orientiert"?!
d.h. also dass Dennis M. Ritchie 1972 schon die heutigen Rechnerarchitekturen kannte und beim Design der Sprache berücksichtigt hat? Wohl kaum.

"Sprachkern ist relativ klein und enthält nur wenige hardwareabhängige Bestandteile"?!
Was ist ein hardwareabhängiger Bestandteil? Ein C Compiler übersetzt ALLE Bestandteile des Quellcodes in Maschinesprache, und somit greifen alle Codebestandteile auf die jeweilige Rechner(hardware) zu, und nicht nur WENIGE.

Die Autoren erklären, dass sie C90 als Basis verwenden und C99-Neuheiten ggf. kennzeichnen, greifen aber schon unmittelbar danach fehl mit der Verwendung des C99-Kommentarzeichens "//" OHNE entsprechende Kennzeichnung.

Die Autoren verwenden viele deutsche Übersetzungen von englischen (Standard)Fachbegriffen, bei "Zwischenraumzeichen" statt white-spaces wirkt das aber schon sehr gekünstelt.
Ebenso verwenden sie durchgängig den Begriff Vektor statt Array, was aber schon allein als Abgrenzung zu vector in C++ sinnfrei und irreführend ist. Das führt dann in der Konsequenz dazu, dass auch andere eingeführte Fachbegriffe aus dem Standard verunstaltet werden, statt variable length array (VLA) heißt es dann bei den Autoren "Vektor variabler Länge".

"Externe Bezeichner-Namen sind durch 8 Zeichen signifikant" ist auch falsch, da der Standard hierfür 6 vorsieht, auch ist die Behauptung falsch, externe Bezeichnernamen (also z.B. Funktionsnamen) wären caseINsensitiv, nur weil es nach Autorenmeinung "einige Linker" gibt, die dies so akzeptieren. Der C-Standard sieht keinerlei Vorgaben für einen Linker vor und für den Compiler sind Funktionsnamen definitiv casesensitiv, wie alle anderen Bezeichner in C auch.

Die Autoren geben für die int-Typen konkrete Wertebereiche an, ohne darauf hinzuweisen, dass dies implementierungsabhängig (also vom Compiler abhängig) ist, der Standard schreibt hier konkrete (absolute) Mindestbereiche vor, die die Autoren aber verschweigen. Auch verzichten die Autoren auf die CHAR_BIT Konstante und deren Beduetung für die Bytebreite aller numerischen Datentypen.

Gravierend ist dann schon das offenkundige Unverständnis der Autoren bei:
"... ein Stringliteral heißt auch Stringkonstante obwohl der belegte Speicherbereich verändert werden darf ..."
was falsch ist, denn der Standard definiert etwas anderes:
'ein Stringliteral, außer, wenn es als Initialisierer für ein char/wchar_t Array dient, ist ein Objekt mit static store duration, wobei das Ändern eines Elements undefiniertes Verhalten bedeutet' also eindeutig NICHT änderbar ist.

Wenig Mühe gaben sich die Autoren auch beim Abschreiben der obligatorischen Operator-Vorrang-Tabelle: hier geben sie für das unäre "*" und "&" eine falsche Assoziativität ggü. (type) an (Zeile 2).

Didaktikschwächen offenbaren die Autoren ebenso:
"ein Cast-Operator darf nur auf Objekte mit skalarem Typ angewendet werden" ohne Erklärung, was Skalartypen sind; das findet der Leser erst später im Buch.

Relativ naive Vorstellungen haben die Autoren auch beim Codedesign:
"es ist GUTER Programmierstil, bei einer notwendigen Typanpassung diese explizit mit einem Cast-Operator durchzuführen. Dadurch wird die Typumwandlung sichtbar und eine Warnung des Compilers vermieden."
- Eine "notwendige" Typanpassung lässt meistens auf mangelnde Sorgfalt beim Programmdesign schließen und das "Vermeiden" einer Compilerwarnung (durch Cast) ist NIEMALS "GUTER Programmierstil".

"...bei Zuweisungen wird der Wert des rechten Operanden in den Typ des linken Operanden konvertiert...":
Was passiert bei Überläufen? Das vom Standard hier vorgesehene Verhalten bleiben die Autoren schuldig.

Beim Thema Zeiger und Array vergessen die Autoren auch wieder etwas:
die Ausnahme beim Adressoperator (&), wo das Array nämlich nicht in einen Zeiger zerfällt.

Die 2.Hälfte des Buches beschreibt die C-Standardbibliothek.
Diese ist aber kaum als Referenz brauchbar, da die einzelnen Funktionen nach Kategorien gruppiert wurden (Datei,String,math,...).
Für eine globale Suche nach Funktionsnamen muss man also das Inhaltsverzeichnis bemühen.
Die Include-datei wchar.h wird als C99-Neuheit genannt, was falsch ist, da schon mit C95 hinzugekommen.
Oftmals beschreiben die Autoren hierbei auch nicht den Rückgabewert von Funktionen, z.B. bei fopen.
Bei fopen wird "t" als Parameter für Textdateien beschrieben, was durch den Standard NICHT abgedeckt ist.
Bei printf wird %N als Format aufgezählt (korrekt ist %n), ebenso %P (statt korrekt %p).

Fazit:
Das Buch hat einige Mängel im Inhalt und bei der Sorgfalt der Autoren und ist deshalb wenn überhaupt nur eingeschränkt zu empfehlen.
Es ist kurz aber NICHT gut, sondern bestenfalls brauchbar.
Von einem teilweise habilitierten Autorenpaar darf man in einem "1.korrigierten Nachdruck von 2004" erwarten, dass keine Anfängerfehler vorkommen.
Wegen der Darstellung eines Cast als "guten Programmierstil" nur ein mangelhaft.


C Programmierung: Programmieren mit einfachen Beispielen (easy)
C Programmierung: Programmieren mit einfachen Beispielen (easy)
von Jürgen Wolf
  Broschiert

9 von 12 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen Fehlerhaft, inkompetent, einfach nur schlecht, unbrauchbar, 29. April 2012
Das Buch ist einfach nur schlecht. Die naive Verständnislosigkeit des Autors zu C-Grundlagen kommt ständig zum Vorschein. Mit seinen Erklärungsversuchen und fehlerhaftem Beispielcode kann der Leser nur verlieren. Das Buch ist niemandem zu empfehlen.
Das Buch richtet sich an C-Neulinge, die im Selbststudium die Sprache C erlernen wollen. Der Autor selbst lernte Programmieren 'ohne Schulbank', strukturiertes Lernen ist dem Autor wohl auch deswegen unbekannt wie man auch an seinen anderen inkompetenten Lehrbüchern unschwer erkennen kann s.u.

'Der Fokus wurde auf Qualität nicht auf Quantität gelegt, ohne auf wesentliche Aspekte zu verzichten' -> von Qualität kann hier überhaupt nicht die Rede sein und die wenigen kurzen Beispielcodes sind vielfach auch noch falsch oder inkonform zum C-Standard.
'... ich möchte Sie nicht mit Begriffen aus dem Fachjargon oder trockener Theorie konfrontieren' -> ist beim Autor auch nicht möglich, da er diese Begriffe selbst nicht verstanden hat und wenn er sie dann doch mal verwendet, greift er fehl, s.u.

Der Autor wird als 'Vollprofi' bezeichnet, dessen 'große Stärke' darin liegt, 'die meist doch recht komplizierten Inhalte' für den Leser klar und verständlich aufzubereiten. Nichts von alledem stimmt. Wie in seinen anderen Werken überwiegen auch in diesem Buch naives Grundlagenunverständnis und fehlerhafter Beispielcode.
Das Buch ist auch didaktisch misslungen, wichtige Grundlagen werden wenn überhaupt erst in Nachhinein erklärt und ohne vorher darauf hinzuweisen (dass die Erklärung später erfolgt), z.B. erklärt der Autor ANSI-C als Grundlage in seinem Buch erst ziemlich am Ende, nimmt zuvor aber häufig Bezug darauf.
Kurz vor Schluss im Kapitel 'Präpozessordirektiven' erfährt der Leser dann an einer Textstelle, dass es den ANSI-C Standard gibt, nachdem (lt. Autor) die Bibliothek genormt ist; dass der Standard auch und in erster Linie die C-Sprachmittel und Syntax außerhalb der Standardbibliothek normt, erfährt der Leser nicht. Solche wichtigen Informationen, dass der Autor sein Buch auf ANSI-C aufgebaut hat, gehören entsprechend hervorgehoben an den Anfang eines Fachbuches und nicht versteckt in das vorletzte Kapitel.
Immerhin bestätigt der Autor:
'Damit man aber Programme schreiben kann, die auf fast jedem System laufen (wie in diesem Buch), wurden einige Headerdateien vom ANSI-Komitee standardisiert', d.h. der Autor bestätigt hiermit selbst noch mal die Vielzahl seiner zuvor gemachten Fehler in seinen Erklärungsversuchen und Beispielcode, die UB (undefined behavior) hervorrufen oder im Standard als "implementierungsabhängig" beschrieben sind und ein Compiler hierbei die konkreten Werte/Verhaltensweisen selbst festlegt.

- der Autor handelt widersprüchlich, einmal listet er die Basisdatentypen mit long double auf, einmal ohne
- im Klappentext:
float: -3.4e+38 ... 3.4e+38
double: -1.79e+308 ... 1.79e+308
-> beides falsch, ANSI C schreibt mit (absolute) Mindestgrenzen für Fließkommawerte vor: -1.e37...1.e37, und für Typgrößen schreibt der Standard nichts vor (außer char == 1), was den Autor aber nicht daran hindert, im ganzen Buch wiederholt Aussagen zu Typgrößen zu machen
- 'gcc -o hallo hallo.c' wird vom Autor empfohlen, statt des anfängergerechten 'make hallo'
- '... natürlich lassen sich die Beispielquellcodes auch mit jedem anderen C- bzw. C++ Compiler verwenden' -> kein Hinweis auf den C-Standard, der dieses überhaupt erst garantiert (wenn die Programme standardkonform sind ebenso wie die Compiler -- andernfalls laufen die Programme eben NICHT auch mit anderen Compilern)
- hallo.c wird nur 1 Seite später plötzlich zu hallo.cpp, Autor behauptet, Include-Dateien gibt es auch als *.hpp, -> falsch, nur in C++ gefordert, kommt davon, wenn man Bücher über C und C++ schreibt und dabei den Überblick verliert
> return 0; 'wird verlangt in main' ->falsch, nur in C89, nicht ab C99
> "//" Kommentarzeichen -> falsch, nicht in C89, erst ab C99
der Autor verwechselt hier beide Seiten
- 'in C beginnt jede Variablendeklaration mit einer Angabe des Datentyps' -> falsch, auch hier verwechselt der Autor wieder Grundlagen, diesmal Deklaration/Definition; richtig und standardkonform ist ' in ANSI-C beginnt jede Variablendefinition mit der Angabe des Datentyps' und ' in ANSI-C beginnt jede explizite Variablendeklaration mit dem storage class specifier extern'

Durchgängig verwechselt der Autor Deklaration mit Definition:
- 'eine Variable kann man auch direkt bei der Deklaration initialisieren' -> grundlegend falsch, niemals kann man bei einer Deklaration einer Variablen diese initialisieren, nur bei der (einmaligen) Definition ist dies möglich, eine Deklaration ist ggü. Definition auch mehrfach im Programmcode möglich;
int i = 1; /* Definition mit Initialisierung, OK */
extern int i = 1; /* Deklaration mit Initialisierung, funktioniert NICHT */
...
extern int i = 2; /* weitere Deklaration der zuvor definierten Variablen i z.B. in einem anderen Sourcefile; -> auch hier falsch, d.h. KEINE Initialisierung möglich */
'Wenn Sie eine Variable im Programm deklarieren, wird dafür im Arbeitsspeicher Platz reserviert' -> falsch, niemals wird bei einer Deklaration Speicherplatz reserviert, nur bei einer Definition.

- printf("%d" für short-Variable -> muss gemäß Standard %hd heißen und ist nur wegen hier greifender default-argument-promotion kein UB
Bei der Erklärung von Datentypen aus mehreren Bytes anhand vom Typ short vermeidet es der Autor, Fachbegriffe wie Byteorder oder Zweierkomplement überhaupt zu erwähnen geschweige denn in seinem Beispiel zu erklären, auf vielen Systemen liegt little-endian vor, also ist die Erklärung des Autors zumindest hierbei unbrauchbar und für den Leser irreführend, wenn er behauptet, der Speicherbereich beginnt mit dem höchstwertigen Bit/Byte.
- bei printf wird wiederholt "%lf" für double und "%d" für size_t verwendet, beides UB im vom Autor referenzierten ANSI-C(89)
Auch die explizite Erläuterung des Autors ist hier fehlerhaft:
'als Formatbezeichner für ... double wurde %lf festgelegt' -> falsch, festgelegt wurde im vom Autor referenzierten ANSI-C(89)Standard unmissverständlich %f für double bei printf; der Autor verwendet also %lf nicht nur in seinen konkreten Beispielcode falsch sondern erklärt es auch explizit falsch, der Autor hat nichts verstanden.

Überhaupt scheint der Autor Schwierigkeiten im Verständnis zu Fließkommazahlen zu haben:
- 'float kann Werte mit Genauigkeit von 7 Stellen speichern' -> falsch, float kann Werte mit Genauigkeit von FLT_DIG Stellen (inkl. Vor- UND Nachkommastellen) speichern, dasselbe Wirrwarr nennt der Autor bei double und long double, wo die Mindestwerte für Signifikanzstellen von 6/10/10 vom Autor wieder ignoriert und somit falsch dargestellt werden
- beim % remainder/modulo operator -> ohne Hinweis auf implementierungsabhängiges Verhalten des Resultats bei Operanden <= 0
- bei der Auflistung der Funktionen aus <math.h> fehlt ldexp, die Auflistung ist nicht alphabetisch, sodass ein Nachschlagen im Buch mit unnötig viel Aufwand verbunden wäre; 1:1 richtig aus der Primärliteratur abzuschreiben gelingt dem Autor auch nicht
- 'da signed die Voreinstellung für Datentypen ist, kann dieses Schlüsselwort weggelassen werden' -> wieder falsche Verallgemeinerung des Standard, für den Datentyp char sogar wieder mal UB
- char-Wertebereich von -128...127 und char 8 Bit groß ist -> falsch, char ist genau CHAR_BIT Bits groß und der Wertebereich ist implementierungs (d.h. Compiler-) abhängig

Die Code-Beispiele des Autor im ganzen Buch sind durch sinnlose Aufeinanderfolge von teilweise nicht-compilierbaren Schritten gekennzeichnet:
> int main()
> {
> return 0;
> }

> int main()
> {
> int
> return 0;
> }

> int main()
> {
> int i;
> return 0;
> }

> int main()
> {
> int i=1;
> return 0;
> }

> int main()
> {
> int i=1;
> i = i + 1;
> return 0;
> }

> int main()
> {
> int i = 1;
> i = i + 1;
> printf("%d",i);
> return 0;
> }
Also jeweils eine gesamte Codewiederholung mit Ergänzung um eine neue Anweisung, obwohl diese neue Anweisung sowieso schon farblich hervorgehoben ist. Dieses Verfahren soll offenbar zum Füllungsgrad des Buches beitragen, ist aber nur ein sinnloses und wie gesagt teilweise sogar nicht-compilierbares Aufblähen.

- bei tabellarischer printf-Formatauflistung schreibt der Autor dann wieder plötzlich, "%f" sei für float UND double gedacht, verwendet es aber in seinem eigenen Buch zuvor und danach nicht in dieser korrekten Form, auch greift er wieder fehl indem er behauptet, für long double sei 'l' vorzustellen -> falsch und UB, es muss 'L' sein
- 'scanf hat dieselben Formatbezeichner wie printf' -> auch wieder falsch
hier verzichtet der Autor auf eine Tabelle mit den scanf-Formatbezeichnern (aus seiner Sicht konsequent, denn die sind ja 'dasselbe'), hätte er es mal getan, wären ihm vielleicht seine grundlegenden Fehler aufgefallen; gipfeln tun seine Fehler zu scanf jedoch: 'im Formatstring dürfen nur Formatbezeichner und NICHT wie bei printf auch Texte oder Steuerzeichen vorkommen' -> komplett falsch und offenbaren wiederum den beschränkten Kenntnisstand und Verständnis von Grundlagen: selbstverständlich kann man im scanf-Formatstring auch sonstige Zeichen verwenden und im Standard ist sogar festgelegt, dass sie nicht ignoriert werden sondern sogar etwas bewirken
- Empfehlung von fflush(stdin); zum Löschen des Tastaturpuffers -> falsch weil UB, die vom Autor präsentierten Alternativen sind ebenso untauglich, z.B.
> char c;
> scanf("%c",&c);
> getchar();
> ...
scheitert bei Eingabe von mehr als 1 Zeichen mit anschließendem <ENTER>
- offensichtlich ist dem Autor die fflush(stdin)-Problematik auch schon aufgefallen: 'Leider lässt sich dies nicht auf jedem System so einfach realisieren' ohne aber die richtigen Schlüsse zu ziehen (UB) und überlässt es dem Leser, das 'auszuprobieren'...'ob es auf ihrem System funktioniert oder nicht, können sie mit folgendem Programm testen...' und präsentiert hier wieder unverändert fflush(stdin); - der Autor begreift einfach nicht, dass man nur Standardfunktionen standardkonform verwenden muss, und schon läuft es auf JEDEM System und zwar ohne es jeweils ausprobieren zu müssen; standardkonformes Arbeiten nimmt einem Programmautor also solcherlei 'Ausprobier'Arbeit ab, das begreift der Autor offenbar nicht und wendet es selbst nicht an; der Autor führt hier wie auch an vielen anderen Stellen im Buch durch eigene Inkompetenz und beschränkten Verständnishorizont den Leser in die Irre
- bei
> int funktion(int arrayname[])
behauptet der Autor wiederum falsch: 'ein Indexwert darf nicht angegeben werden'
Selbstverständlich darf standardkonform hier ein Indexwert (korrekt heißt es hier: Elementanzahl) angegeben werden
- 'als String bezeichnet man eine Kette von Zeichen' -> falsch, hier fehlt die zwingend notwendige Aussage zum terminierenden '\0', die einen String von einen char-Array unterscheidet
- ein einzelnes Anführungsstrichzeichen (') ist beim Autor ein Sonderzeichen innerhalb von Strings das sonderbehandelt werden muss -> falsch, printf(" ' "); ist sehr wohl möglich
- scanf liest bei Strings nur bis zum ersten Leerzeichen ein -> falsch, der Autor offenbart Unkenntnis über die Formatbezeichner von scanf, genau die, von denen er zuvor behauptet hatte, sie wären gleich zu printf; Leerzeichen innerhalb von Strings sind sehr wohl mit scanf einlesbar
- Autor offenbart wieder mal seine Unkenntnis, indem er die scanf-Möglichkeit zur Begrenzung der Stringlänge 'vergisst' und stattdessen auf fgets verweist
- naive Aussage 'fgets hängt \n am Ende des Strings mit an' -> falsch, fgets liest genau die Zeichen ein, die im Stream vorliegen und bricht nur bei '\0' oder Erreichen des vorgegebenen Limits ab, fgets macht eben keine Sonderbehandlung für '\n'

Der Autor scheitert in seinen Beispielen an simpelsten Aufgabenstellungen und produziert UB, so auch hier:
> char pass[] = {"1234abcd"};
> int main()
> {
> char Passwort[8];
> printf("Passwort eingeben : ");
> scanf("%s",&Passwort[0]);
> if(strcmp(pass, Passwort) == 0)
> printf("Passwort richtig!!!\n");
> else
> printf("Passwort falsch!!!\n");
> return 0;
> }
Gibt hier der Anwender das korrekte Passwort ein (ein Normalfall der Anwendung), liegt UB vor (wegen zu gering dimensioniertem Passwort, Speicher wird über die Arraygrenze hinaus mit '\0' beschrieben), und dass, obwohl der Autor selbst im gleichen Kapitel mehrfach darauf hinweist, dass man auf "ausreichende" Dimensionierung der Strings bzgl. terminierendem '\0' achten soll.
Müßig zu erwähnen, dass hier der Autor auch wieder nicht
- den Tastaturpuffer löscht (eigene Empfehlung des Autor in seinem Buch)
- eingebaute scanf-Funktionalität zur Stringlängenbegrenzung wird nicht verwendet (führt immer zu UB, wenn der Nutzer >7 Zeichen eingibt)
- redundante Verwendung von &Passwort[0] anstatt Passwort
- Definition wird als Deklaration bezeichnet

- beim Thema 'Zahlen in einen String umwandeln' -> Autor 'vergisst' in seiner Auflistung die Standardfunktion strtoul
- zum Thema 'Zeiger und Arrays': '... dass ein Zeiger eines bestimmten Datentyps nur auf eine Adresse zeigen kann, dessen Inhalt vom selben Typ ist' -> neben dem grammatikalischen Fehler ist die Aussage auch sonst falsch, da Zeiger prinzipiell überall hinzeigen können, eine Typgleichheit ist nur bei der Dereferenzierung nötig, z.B. kann jeder typisierte Zeiger auch auf NULL zeigen (kommt sehr häufig vor), und das wäre laut Autor nicht erlaubt -> grundsätzliches Unverständnis des Autors zu C-Grundlagen
Der Autor erklärt hier einführend: '... Zeiger gelten als das Mächtigste, das C zu bieten hat...dass Zeiger gar nicht so kompliziert sind, wenngleich dies immer wieder verbreitet wird.' -> Der Autor überführt sich hierbei selbst der Unkenntnis, die o.g. naiven und falschen Aussagen belegen, dass er selbst eben keinen Überblick und Verständnis vom 'Mächtigsten' in C hat und dass es eben doch kompliziert ist, mit Zeigern richtig umzugehen, was der Autor selbst (unbewusst) beweist.
- 'Im Fachjargon sagt man, dass ... ein Zeiger ... eine Referenz auf die Adresse der Variablen ... ist' -> wie oben erwähnt 'versprach' der Autor ja auf Begriffe aus dem Fachjargon verzichten, hier tut er es doch mal und prompt wieder falsch, korrekt wäre nämlich: "ein Zeiger repräsentiert eine Referenz auf Daten" und NICHT "ein Zeiger repräsentiert eine Adresse auf Daten" -> der Autor widerspricht seinen eigenen (diesmal ausnahmsweise korrekten) einführenden o.g. Worten zu diesem Kapitel; offenbar hat der Autor seine Aussagen in diesem wichtigen Kapitel überall zusammengesucht und verständnislos abgeschrieben

Auffällig auch, dass in den Beispielen des Autors oft Zeigerwerte in Form von 0000:0005 vorkommen, was auf völlig antiquierten Speichersegmentierung aus MSDOS-Zeiten hinweist, offenbar hat der Autor sich auch hier aus seinen anderen Werken bedient und somit auch seine Fehler wiederverwendet.
- abschließend im Kapitel: '... deshalb ist es sehr wichtig, dass Sie dieses Kapitel verstanden haben' -> beim Autor selbst nicht gegeben, deshalb auch wenig wahrscheinlich, dass ein Leser hieraus etwas richtiges lernt
- bei Zuweisung von Strukturvariablen: 'bei älteren Compilern wird eine solche Form der Zuweisung möglicherweise nicht unterstützt' -> falsch, jeder ANSI-C Compiler aufwärts unterstützt dies, eine weiterer Grund, auf die Standardkonformität des Compilers zu achten
- unnötige Verwendung von globalen Variablen in einfachsten Beispielprogrammen durch den Autor, was auch wieder auf Praxisferne schließen lässt
- 'da es kaum noch reine C-Compiler gibt' empfiehlt der Autor das Casten von malloc (wegen C++ Konformität) -> verständnisloses, praxisfernes Argumentieren des Autors, alle verbreiteten Compiler-Hersteller bieten neben C++ selbstverständlich auch einen C Compiler an, man muss nur mal die jeweilige Dokumentation dazu lesen, was der Autor offensichtlich nicht getan hat und sich durch Defaulteinstellungen in diversen IDE hat blenden lassen.

- 'In der Praxis ist es zwar möglich, Arrays dynamisch zu machen. Nur ist dies mit einem höheren Aufwand verbunden'. -> falsch, ein Array ist immer gekennzeichnet durch eine KONSTANTE Zahl von Elementen bei der DEFINITION, d.h. der Autor verwechselt hier die Verwendung von Array-like Zugriffen auf dyn. erzeugten Speicher mit Arrays; er hat auch den Unterschied zw. Zeiger und Array nicht verstanden und verinnerlicht
-in seinem Code-Beispiel zu einer einfachen Lagerverwaltung verwendet der Autor auch wieder laienhafte globale Variablen und fflush(stdin); (UB) und zeigt durch Design von Funktionen wie
> void read_lagerverwaltung(void)
wieder grundsätzliches Unverständnis an der Sprache C als einer Sprache, die wesentlich durch die Flexibilität von Funktionen lebt, die der Autor zwar kennt (zeigt er zuvor) aber in seinen eigenen Beispielen nicht anwendet und so dem Leser wesentliche C-Eigenschaften vorenthält; ohne Parameter und ohne Rückgabewert widersprechen Funktionen den C-Grundprinzipien und müssen über laienhafte globale Variablen Daten austauschen
- die Rangfolge von C-Operatoren wird nur nebenbei bei '&&' und '||' erwähnt, eine Auflistung der Tabelle aller Operatoren mit ihrer Priorität fehlt im ganzen Buch, gehört in jedes C-Fachbuch
- der Autor hat sein eigenes Buch nicht verstanden und verinnerlicht, die zuvor genannten struct wendet er danach im passenden Beispiel-Code nicht an, sondern definiert sie wieder einzeln, z.B.
> char name[20], v_name[20];
> char ort[20], strasse[20];
statt übersichtlich und mit größerem Lerneffekt für den Leser
> struct Person {
> char name[20], v_name[20];
> char ort[20], strasse[20];
> };
Schon bei einfachen und kurzen Beispielen verliert der Autor den Überblick, indem er z.B. die o.g. Beispieldaten mit fgets einliest, statt mit scanf. Das führt dazu, dass die char-Daten jeweils am Ende ein '\n' enthalten, was in der Folge natürlich nur Probleme bereitet, falls man versucht, mit diesen Daten weiter zu arbeiten, auch hier offenbart der Autor grundsätzliche Praxisferne und mangelnde Sorgfalt bei der Erstellung seiner Beispielprogramme für einen C-Anfänger, indem er selbst Anfängerfehler macht, z.B. scheitert solcherlei fgets-Einlesen immer:
> char name[20];
> char meinname[]="jogi";
> fgets( name, sizeof(name), stdin );
> if( strcmp(name,meinname) == 0 )
> {
> printf("Name gleich"); /* hier wird das Programm nie ankommen, da "jogi\n" und nicht "jogi" eingelesen wird */
> }
> else
> {
> printf("Name ungleich"); /* hier immer */
> }
was an der vom Autor übrigens zuvor selbst erklärten fgets-Eigenschaft liegt, auch '\n' mit einzulesen.
- dem Initialisieren einer Struktur widmet sich der Autor gar nicht, obwohl gerade hier ein Anfänger von der impliziten Arbeit des Compiler profitieren kann, umständlich verwendet der Autor
> struct koordinaten punkt;
> punkt.x = 20;
> punkt.y = 5;
statt
> struct koordinaten punkt = {20,5};

Das Buch ist in seiner Gesamtheit völlig misslungen, C-Prinzipien und Grundlagen werden ignoriert oder falsch erläutert und in der überwiegenden Mehrzahl auch in Beispielcodes falsch umgesetzt.
Der lernwillige Leser sollte sich die Lektüre dieses Buches ersparen, es wäre nur Zeitverschwendung, denn er müsste für ernsthafte Anwendung seines C-Wissens C ein zweites Mal und diesmal anhand wirklich kompetenter Fachbücher erlernen und alles hier Gelesene vergessen.

Der Autor ist unfähig, kompetente Fachbücher zu schreiben, das äußert sich auch in der durchschaubaren 'Strategie', dieses Buch nicht als Neuauflage seiner Vorgängerwerke
- 'C - Mit einfachen Beispielen programmieren'
- 'Easy C Programmierung: Mit einfachen Beispielen programmieren-leicht-klar-sofort'
- 'Grundkurs C'
- dem Universalwerk des Unwissens: 'C von A-Z'
anzubieten, leicht erkennbar auch die dort vorhandenen Fehler im Verständnis und Beispielcode, die nur leicht geändert und mit all ihren Fehlern in dieser 'Neuerscheinung' wieder vorkommen. Dieses Buch ist einfach nur der 4. bzw. 5. Aufguss vorheriger untauglicher Fachbücher des Autors und reiht sich nahtlos in die 'Qualität' des 'Vollprofi'-Autors ein.
Das Buch ist niemandem zu empfehlen.
Kommentar Kommentare (2) | Kommentar als Link | Neuester Kommentar: Jun 25, 2012 7:46 PM MEST


C Kompaktreferenz (Programmer's Choice)
C Kompaktreferenz (Programmer's Choice)
von Helmut Herold
  Taschenbuch

1 von 1 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen Fehlerhaft, lückenhaft, inkompetent; untauglich, 22. April 2012
Der habilitierte Autor ist mit seinem Anspruch, ein kompaktes, prägnantes und kompetentes Werk zu schaffen gründlich gescheitert. Das Buch ist niemandem der ernsthaft C erlernen möchte zu empfehlen.

Der Autor offenbart grundsätzliche Unkenntnis und Naivität in Sachen C aber auch beim eigenen Abstrahierungsvermögen und Didaktik.
Der Autor wendet sich an erfahrene Programmierer, die die Sprache C erlernen wollen. Dabei verweist er auf die 'hunderte' von Studenten, die bei ihm C 'erfolgreich' gelernt haben sollen.

Das naive, praxisferne C-Verständnis des Autors offenbart sich schon am Ignorieren des ANSI-C Standards.
Weder erklärt der Autor, dass er sein Buch nach diesem Standard und damit allgemeingültig ausrichtet, noch erklärt er überhaupt, was der ANSI-C Standard ist und welchen Anspruch dieser hat noch seine Bedeutung in der Praxis (Portabilität, Plattformunabhängigkeit,...).
Das hindert den Autor aber nicht daran, das Wort ANSI-C mehrfach zu verwenden. Was ist eigentlich so schwer daran, in einem selbsternannten kompetenten Fachbuch ZU BEGINN eine Begriffsdefinition vorzunehmen und diese dann zu verwenden?

Auch bei konkreten C-Sachverhalten lässt sich diese Didaktikschwäche des Autors erkennen: den Fachbegriff Whitespace führt er erst in ca. der Mitte des Buches (und dann auch noch fehlerhaft s.u.) ein, zu Beginn jedoch zählt er die 6 Zeichen einzeln auf ohne den Begriff zu nennen. Überhaupt verwendet der Autor die eingeführten englischen Fachbegriffe wenig bis gar nicht, sequence point, evaluation, expression, statement, assignment, promotion, behavior, scope, callback u.v.m. sucht man vergebens und findet sie bestenfalls manchmal als deutsche Übersetzung nebenbei.

Gleich am Anfang des Buches macht der Autor den typischen Fehler der Auflistung von angeblichen Wertebereichen und Größenangaben der Basistypen. Er versucht, dieses Unverständnis zu kaschieren, indem er voranstellt, dass es sich um 'typische' Werte handele: Der Standard schreibt bekanntlich nur (absolute) Mindestgrenzen für Wertebereiche vor, die konkrete Implementierung und Besetzung der symbolischen Grenzen (INT_MAX,INT_MIN) ist Sache des Compilerherstellers. Zu Größenangaben macht der Standard (außer char==1) keinerlei Vorgaben, was den Autor aber nicht daran hindert, wieder bitgenaue Größenangaben für jeden Typ zu machen. Später im Buch korrigiert sich der Autor dann (offenbar unwissentlich) selbst, indem er die im Standard formulierten Mindestgrenzen (ausnahmsweise mal korrekt) aus dem Standard abschreibt. Diese Widersprüche sprechen auch nicht gerade für den Überblick des Autors über sein eigenes Werk.
Ebenso nicht die Unbestimmtheit, die ANSI-C zum Datentyp char macht:
- Wertebereich char: -128...127 -> später im Buch und nebenbei wird dann erwähnt, dass ANSI-C hier nichts vorgibt, d.h. weder signed noch unsigned
- sämtliche Integraltypen werden jeweils mit UND ohne Typ-Specifier aufgelistet, also long und long int jeweils extra, short und short int, usw. ohne Hinweis des Autors über die Äquivalenz
- Variablennamen dürfen beliebig lang sein -> falsch, das logical sourceline-Limit liegt bei ANSI-C bei 509 Zeichen, auch 'vergisst' der Autor hierbei die standardgemäße Signifikanz (31/6) der initial-chars bei Bezeichnern zu benennen

Bei symbolischen Konstanten
> #define MAX 100
> const int max = 100;
'vergisst' der Autor wiederum auf den wichtigen Unterschied ( Compilezeit/Runtime-Konstante ) zu verweisen, Hinweise zum Gebrauch von enum-Elementen als Konstanten unterbleiben vorsichtshalber gleich ganz
- bei getchar() u.ä. spricht der Autor häufig von RETURN-Taste und ASCII-Wert 10, statt korrekt vom standardgemäßen '\n'
- bei sizeof 'vergisst' der Autor dessen Returntyp size_t einzuführen (geschieht erst nebenbei viele Kapitel später) und verwendet ihn auch mit falschem Formatspecifier bei printf("%d", was undefined behavior (UB) für das Programm bedeutet
- der Fachbegriff 'undefiniertes Verhalten' wird ohne Erklärung verwendet, obwohl der Standard hier konkrete Vorgaben macht, insbesondere die Abgrenzung zu unspezifiziertem und implementierungsabhängigem Verhalten
- "%n" bei printf liefert Zeiger auf Ganzzahl -> falsch Zeiger auf int

Unerklärlich für einen Autor, der auch Fachbücher zu Linux schreibt ist, dass er ANSI-C Vorgaben auf das hosted environment, sprich das Betriebssystem ableitet indem er behauptet, dass Kommandozeilenparameter-Strings (main-argv) an Whitespaces separiert werden, was falsch ist. ANSI-C macht überhaupt keine Vorgaben an das hosted environment (z.B. eine Linux-Shell), das würde dem allgemeingültigen Charakter eines Standards auch widersprechen; die Separierung der Argumente und Übergabe an den Prozess wird von der Shell selbst vorgenommen, oftmals sogar konfigurierbar ( IFS= u.ä. je nach Shell).
Bei der Vorstellung von scanf erfolgt zwar der Hinweis über den vorhandenen Returnwert, aber nicht, dass man dieser sehr komfortabel zur Fehlerbehandlung der Eingabe nutzen kann, konsequenterweise verwendet der Autor diesen Wert dann auch niemals in einem seiner Beispielcodes.
Im Abschnitt 'Reihenfolge der Abarbeitung von Eingaben bei scanf' unterlässt der Autor den hier passenden und wichtigen Hinweis zur Unbestimmtheit der Reihenfolge der Evaluierung der einzelnen Parameter; dies geschieht wiederum erst sehr viel später in einem anderen und vor allem allgemeineren Zusammenhang.

- 'signed/unsigned overflow - ANSI C schreibt hierfür nichts vor' -> falsch, ANSI C schreibt hier sehr wohl etwas vor, nämlich für unsigned wrap-around und für signed-arithmetic-overflow UB und signed-assignment-overflow Implementierungsabhängigkeit
- Erklärung von TRUE/FALSE Semantik, aber keine Erklärung der Evaluierung von logischen Ausdrücken immer zu 0 oder 1 durch den C-Standard
- beim condition-operator ?; erfolgt kein Hinweis zur Promotion des Ergebniswertes auf den "höchstwertigen" Typ
- 'eine leere Parameterliste bei Funktionsprototypen (ohne explizites void) kennzeichnet eine leere Parameterliste' -> falsch , kennzeichnet eine unbekannte aber feste Anzahl von Parametern (also auch kein variadic)
- Nennung 'call by reference' bei Funktionen mit Beispiel obwohl unmittelbar zuvor gesagt wurde: 'in C gibt es nur Wertübergabe'
- wie schon falsch bei size_t/"%d" verwendet der Autor auch häufig falsch "%lf" für double bei printf, auch wieder UB
- char s[]="abc" wird wie bei vielen anderen Stellen auch sowohl als Deklaration wie als Definition bezeichnet, ohne Hinweis auf die Unterschiede beider Fachbegriffe hinzuweisen
- Unterschiede Arrayname vs. Zeiger: unvollständige Auflistung der Unterschiede gemäß Standard
- toupper/tolower(char-var) -> UB, weil hierbei immer unsigned char verlangt wird
- scanset bei scanf vorgestellt scanf("%[ABCDEFGHIJKLMNOPQRSTUVWXYZ]") statt einfacher scanf("%[A-Z]")
- Unsicherheit bei clock_t/clock(), indem er CLOCKS_PER_SEC als double-Typ ansieht, was aber nicht standardkonform ist, der Standard sagt nichts darüber aus, deswegen auch hier wieder UB
> printf("%f",(ende-start)/CLOCKS_PER_SEC);
- sinnfreie Unterteilung von Arrays in statisch und dynamisch -> falsch, der Autor selbst hat zuvor in seinem Werk (richtig) erkannt, dass Arrays bei ihrer Definition durch eine KONSTANTE Anzahl Elemente gekennzeichnet ist, widerspricht dem nun aber wenig später schon wieder

Im Kap. 'Konvertierung von void-Zeigern' zeigt der Autor beispielhaft an char *s=(char*)malloc(...); ohne auf die ohnehin in C schon vorhandene implizite verlustfreie Promotion solcher Zeigertypen hinzuweisen, die in C++ notwendig ist aber nicht in C ; bei dieser Kapitelüberschrift lässt dies schon auf vorhandenes Unverständnis dieser C-Grundlage schließen. Diese überflüssigen Typecasts bei malloc/calloc/realloc benutzt der Autor bei jeder Gelegenheit.

- Größe einer struct in Bytes ergibt sich aus der Summe der Bytegrößen aller Einzelelemente; -> falsch, Summe ergibt sich genau aus sizeof(struct type), d.h. also inkl. evtl. inner und trailing padding bytes
- Größe einer union richtet sich nach der Größe des größten Einzelelements -> falsch, Größe einer union ist ausschließlich sizeof(union type)
- 'sscanf arbeitet wie fscanf statt mit FILE auf Strings' -> unzulässig verallgemeinernd, da fscanf den Filepointer/Inputstream verändert, sscanf den String/Inputstream jedoch nicht
- 'unter Linux kein Unterschied zw. Text/Binärdateien, deswegen fopen(...,"r""rb") uninteressant; unkonkret und praxisfern, da durchaus auch unter Linux MSDOS-formatierte Textdateien vorkommen können; wie gesagt: der Autor schreibt auch Bücher für Linux(!), da sollte ihm sowas auffallen
- remove liefert im Fehlerfall -1 -> falsch, liefert ungleich 0
- 'für Verzeichnisse ist remove identisch zur Funktion rmdir' -> falsch, ANSI C kennt keine Verzeichnisse, demzufolge unspez. Verhalten
- fflush:
'Wenn fflush auf eine Datei angewendet wird, von der zuletzt gelesen wurde, liegt ein undefiniertes Verhalten vor.' Im unmittelbar folgenden Satz dann: 'Um z.B. alle noch im Standardeingabepuffer befindlichen Zeichen zu entfernen, muß nur fflush(stdin) aufgerufen werden'. Der Autor weiß also nicht mehr, was er im Satz zuvor gesagt hat, nämlich dass fflush(stdin) zu UB führt; was ihn auch nicht daran hindert, wie schon gesagt, fflush(stdin) häufig in seinen Beispielen einzusetzen und explizit zu empfehlen
- im Kapitel 'Elementare E/A-Funktionen' erfolgt die übergangslose Auflistung von Nicht-ANSI-C Funktionen open/close/read/write ohne jeglichen Hinweis auf deren POSIX Konformität, auch hier wieder bemerkenswert, dass POSIX zwar verwendet aber nirgendwo erklärt wird und dass wie schon erwähnt, von einem Linux-Fachbuchautor
- normales Beenden der Funktion main auch ohne return möglich; falsch -> nicht ANSI-C konform
- Beenden des Prozesses auch mit _exit() möglich ; -> kein ANSI-C, in C99 heißt es korrekt _Exit()
- wieder keine saubere Trennung zw. ANSI-C und POSIX bei
> extern char **environ;

- Auflistung der Konstanten in Standard-Headerdateien ist fehlerhaft, z.B. NAME_MAX,PATH_MAX,OPEN_MAX,SSIZE_MAX (nur POSIX), dafür fehlt z.B. FILENAME_MAX, auch falsche Minimalwerte aufgeführt, z.B.
INT_MIN -32768 (statt richtig -32767)
LONG_MIN -2147483648 (statt richtig -2147483647)
Der Autor hätte hier einfach nur Kap. A.4 auf dem Standard richtig abschreiben müssen, das kann eigentlich nicht so schwer sein.

- scanf mit Format "%c" liefert nicht wie vom Autor genannt eine Zeichenkette, sondern eine Folge von char OHNE terminierendes '\0'
- viele Seiten mit identischem Inhalt, beispielsweise zu nahezu allen Funktionen aus der Standardbibliothek erfolgt deren Erläuterung mehrfach, z.B. im Kapitel zu Dateien und dann noch mal beim Kapitel zur Headerdatei <stdio.h>; offenbar will der Autor mit dieser Inhalts-Doppelung den Umfang seines Buches erhöhen; soviel zum Anspruch des Autors für sein Buch 'kurz und prägnant'
- im Kapitel 4 'Wichtige Algorithmen' werden bei Quicksort wieder die zuvor schon genannten Texte und Beispielcodes kopiert

Über 100 Seiten widmet sich der Autor dem Thema Suchen/Sortieren im Kapitel 'Wichtige Algorithmen', fertige Algorithmen/Datenstrukturen inkl. Beispielcodes zusammenzusuchen und dann aufzulisten liegen dem Autor eindeutig mehr als konkrete C-Grundlagen; leider vermisst man hier die in der Informatik wichtigen Baumstrukturen (diese werden nur in einfachster Form auf 6 Seiten dargestellt) und den Algorithmen dafür; die Beispiele sind die üblichen Kandidaten wie ggT, Türme von Hanoi, Primzahlen; dabei scheint er aber die Beispielcodes 1:1 kritiklos übernommen zu haben, und macht dabei dann auch prompt den Anfängerfehler bei der cmp-Funktion zu qsort:
> int cmp(const void *x,const void *y) {
> return *(const int*)x - *(const int*)y;
> }
die bekanntlich bei größeren (Absolut)Werten leicht overflows erzeugt.
Die häufige Verwendung von globalen Variablen und auch wieder der unsicheren Funktion gets statt fgets/scanf spricht wiederum für die Praxisferne des Autors.
Ob überhaupt und wenn ja in welchem Umfang eine Detailübersicht über Such/Sortieralgorithmen in eine 'kurz prägnante' C Kompaktreferenz gehört, ist zumindest zweifelhaft.

Im dann wieder konkreteren Kapitel 'Nützliche Programme und Hilfsroutinen' geht dann schon wieder einiges schief, z.B.
> long z;
> ...
> if( z>=LONG_MAX || z<=LONG_MIN ) ...
ist das '>' bzw. '<' redundant und zeugt nicht vom Überblick des Autors über seinen Code.

Zum Thema 'Sichere Zahleneingabe' via strtol,strtoul,strtod vermeidet der Autor u.a. das zwingend notwendige errno/ERANGE und fragt auch den returnwert falsch ab, sodass dieser vorgestellte Code wenig sinnvoll ist und nicht in allen Varianten richtig arbeiten kann.

Müßig zu erwähnen, dass der Autor seine eigenen Routinen zur 'sicheren' Zahleneingabe in den folgenden Codebeispielen NICHT verwendet, wie im ganzen Buch vermeidet er einfachste Fehlerbehandlungen wie die Auswertung des Returnwertes von scanf u.ä.

Mühsam versucht der Autor in einem Beispiel seiner 'nützlichen' Tools, deutsche Kommazahlen einzulesen um damit zu rechnen; dazu bemüht er eine struct
> struct k_zahl {
> long vorkomma;
> unsigned long nachkomma;
> } zahl;
und Stringfunktionen zur Aufteilung in Vor- und Nachkommateil, um dann in ca. 40 Codezeilen zum gleichen Ergebnis zu kommen wie z.B.
> if ( setlocale(LC_NUMERIC,"german") && scanf("%lf",&doublevar)==1 )
>
Kein Wunder, locales kommen im ganzen Buch auch nirgends vor. Dass der Standard für Sprach/Umgebungsabhängigkeit durchaus etwas anbietet, ist dem Autor offenbar unbekannt.

Im Kapitel "Semigrafik" stellt der Autor conio.h aus Turbo-/Borland-C vor, anstatt die vom ihm selbst im Folgekapitel vorgestellte plattformübergreifende ncurses-Lib zu verwenden; wie schon gesagt, ein Autor der auch Linux-Bücher schreibt, sollte diese UNIX-basierende Bibliothek inkl. der Portierung auf MSDOS/Windows basierende Systeme kennen (conio.h ist bekanntlich kein C-Standard und somit nicht plattformunabhängig).

Das Kapitel 'Programmierung der Maus unter DOS' kann man nur noch als antiquiert bezeichnen, so was gehört bestimmt nicht in eine 'kurze prägnante' C Kompaktreferenz.

Der Autor offenbart mit seinem Werk grundlegendes Unverständnis zu wesentlichen Grundlagen der C-Programmierung, und präsentiert in der immerhin schon 3. Auflage seines Buches (1999,2002,2005) große Lücken, Fehler bei Sachverhalten und Fachbegriffen wie bei konkreten Beispielcodes. Er präsentiert widersprüchlich und didaktisch unsicher.

Der Autor präsentiert weder C-Styleguides noch beschreibt der den praktischen Umgang der C-Programmierung im Umfeld von IDE, Compiler, Debugger, Lint, Testframeworks und Sourcecode-Verwaltungstools.

Ein Literaturverzeichnis sucht man vergebens, das Manöver des Autors, dieses Buch als 'Kompakt'referenz zu präsentieren und für konkretere Dinge dann auf seine eigene, weiterführende Literatur in 3 (bestellbaren) Bänden verweist um damit eventueller Kritik an diesem Werk zu begegnen, ist leicht durchschaubar.

Das Buch ist der o.g. Zielgruppe der erfahrenen Programmierer wie auch niemandem sonst zu empfehlen, die 'erfolgreich' nach diesen Unterlagen ausgebildeten 'hunderte' Studenten dürften in der Praxis eher mit negativen Überraschungen rechnen, falls sie versuchen, das hier vermittelte Wissen anzuwenden.
Das Buch ist aus oben geschilderten Gründen weder kurz, noch kompakt, noch kompetent, und prägnant nur in negativer Hinsicht und kann deswegen keinesfalls als 'Referenz' weder im allgemeinen noch im konkreten Sinn dienen.
Das Buch ist niemandem zu empfehlen.
Kommentar Kommentar (1) | Kommentar als Link | Neuester Kommentar: Dec 27, 2012 8:17 PM CET


Seite: 1 | 2