Profil für Max > Rezensionen

Persönliches Profil

Beiträge von Max
Top-Rezensenten Rang: 11.168
Hilfreiche Bewertungen: 375

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

Rezensionen verfasst von
Max

Anzeigen:  
Seite: 1 | 2 | 3
pixel
Programmieren in C
Programmieren in C
von Robert Klima
  Taschenbuch
Preis: EUR 49,99

4 von 6 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen Veraltet, oberflächlich, fehlerhaft, naiv, 9. Februar 2015
Rezension bezieht sich auf: Programmieren in C (Taschenbuch)
Die beiden habilitierten und promovierten Autoren von der TU Wien wenden sich an Einsteiger und erfahrene Programmierer mit ihrer 'grundlegenden und fundierten Behandlung der Sprache C'.
Dieses Ziel können sie bei weitem nicht erfüllen, die eigene laienhafte Vorstellung von 'komplexen Problemen' an die sie Leser 'ohne Vorkenntnisse in C oder Programmierung' heranführen wollen, hindert sie daran.
Keinesfalls wird durch die Autoren der 'Sprachumfang kritisch betrachtet' und 'typische Fallen vermieden'.
Dazu wäre ein Grundverständnis der Sprache C mit seinen Standards notwendig und bei den Erläuterungen ein gewisses
Maß an Abstraktion und Übersicht über Zusammenhänge.
All das bieten die Autoren in keinster Weise, ihr Werk bleibt Stückwerk, der Leser erhält keineswegs einen zusammenhängenden Überblick über die Sprache aufgrund der fehlenden Bezüge, die die Autoren aus den einzelnen Themen (nicht) ableiten.
Größtes Manko dieses Werkes ist es, dass die Autoren sich in keinster Weise an die C-Standards halten, sie erwähnen auch nicht, auf welchen Standard (C89 od. C99) sie sich in ihren Beispielcodes und Erläuterungen beziehen;
demzufolge ist das gesamte Buch mit unklaren Aussagen durchsetzt,
'die meisten Compiler'
'einige Compiler'
'meistens'
Die Autoren begreifen einfach nicht, dass diese Formulierungen für einen Einsteiger in C unbrauchbar sind, zumal sie ebenfalls ihre eigene verwendete Entwicklungsumgebung (Compiler,Plattform) nicht beschreiben, der Leser muss jederzeit damit rechnen,
dass die gezeigten Beispielcodes und Erläuterungen in seiner Umgebung nicht funktionieren bzw. zu Fehlern führen.
Eine konsequente Festlegung auf einen C Sprachstandard ist für ein Lehrbuch unbedingt erforderlich und die o.g. unklaren Aussagen für den Leser zu vermeiden, die Aussagen werden sofort eindeutig:
'alle Compiler'
'kein Compiler'
'immer'
ein unschätzbarer Vorteil gerade in der Lernphase, da der Leser keine Randbedingungen und Voraussetzungen zusätzlich erlernen muss.

Das Layout des Buches ist aufgrund des kleinen Schriftfonts schwer lesbar, die Fußnoten, die nochmal kleiner sind, sind somit noch schwerer lesbar.
Dieses schlechte Layout wird gesteigert, indem in vielen Beispielcodes Stringliterale nochmals kursiv erscheinen.

Bis auf ganz seltene Aussagen zu C99 basiert das übrige Werk auf ANSI C (C89), die Autoren erwähnen dies aber nicht, der Leser muss dies selbst 'schlussfolgern', unhaltbar für ein Lehrbuch.
Grundlegende Begriffe undefiniertes, unspezifiziertes und implementierungsabhängiges Verhalten bleiben unerwähnt.

Konkrete Fehler kommen verteilt in allen Kapiteln vor:
- Präprozessor #undef, #error, #if defined fehlen
- keine C99 Präprozessor-Direktiven, demzufolge auch keine Makros mit variablen Parametern
- error.h wird als wichtige Header-Datei bezeichnet -> ist kein Standard
- für Datentypen float/double/long double werden 32/64>=64 Bit festgelegt -> keine Festlegung im Standard
- cbrt (Kubikwurzel) wird genannt -> erst in C99 vorhanden
- char kann Werte -128...127 annehmen -> Standard legt char implementierungsabhängig fest (unsigned char oder signed char)
- Wahrheitswerte gibt es nicht -> in C99 gibt es _Bool und bool
- die gezeigte Rundung (long)(double-wert + 0.5) -> funktioniert nicht für negative Werte
- snprintf wird genannt ohne Hinweis, dass diese Funktion erst ab C99 existiert
- bei union wird behauptet, dass die Größe einer union der des größten Elements entspricht -> falsch, der Standard schreibt sizeof vor
- Fehlercodes ENOENT,ENOMEM bei Aufruf von Bibliotheksfunktionen werden genannt -> diese sind nicht standardisiert, sondern nur eine Compilererweiterung
- sizeof wird ohne den Rückgabetyp size_t gezeigt und falschem Format "%d" bei printf; dieser wichtige Datentyp size_t kommt im ganzen Buch nicht vor

Auch die weitere Erklärung hierbei zeigt das naive Grundverständnis:
"sizeof ist strenggenommen ein Operator, der zur Übersetzungszeit durch den Compiler ausgewertet wird, hat jedoch in seiner Verwendung die Eigenschaften einer Version"
3 Fehler sind hier gemacht worden:
- Array bei sizeof zerfallen niemals in den Zeiger auf das 1. Element, bei Funktionen zerfallen Arrays immer in den Zeiger
- bei VLA (ab C99) arbeitet sizeof zur Runtime (nicht zur Compiletime)
- sizeof für Objekte benötigt keine Klammer (Funktionen immer)

Unglückliche Formulierungen lassen ebenfalls auf einen Mangel an Überblick schließen:
"Im Folgenden werden einige Befehle der Standard-Bibliothek erklärt, die mit jedem C-Compiler mitgeliefert wird, da sie weitgehend standardisiert sind."
Es sind kein 'Befehle' sondern Funktionen und jedes Element der Standardbibliothek ist standardisiert, ansonsten sind es Compilererweiterungen.

Ungeniert verwenden die Autoren den Datentyp long long int
"manche Compiler unterstützen auch den Qualifizierer long long... Er ist im ANSI Standard jedoch nicht definiert."
Das ist richtig, auch hier fehlt der Bezug zu C99, wo dieser Typ definiert wird.

Bei scanf wird der Datentyp long double 'vergessen', ebenso die Längenbegrenzung bei Strings indem 'empfohlen' wird:
char text[100];
scanf("%s", text);
Weil hierbei Feldgrenzen überschrieben werden könnten, "ist bei praxistauglichen Programmen die Funktion scanf gegen die Funktion fgets zu ersetzen".
Ebenso werden auch andere praxisübliche scanf-Formate 'vergessen'.

Der Adress-Operator wird ausschließlich 'operator &' genannt,
bei der Operator-Vorrangtabelle behaupten die Autoren, diese gibt die Reihenfolge der Auswertung vor -> falsch, die Tabelle gibt lediglich die Zuordnung zum Operanden vor (Auswertung erfolgt später und unabhängig von der Vorrangtabelle)
Diese Grundlage wird dem Leser ebenso falsch vermittelt.

Beim Thema Eingabepuffer präsentieren die Autoren ein wildes Durcheinander,
zuerst
scanf(" %c"); -> leert nur Whitespaces aus dem Eingabepuffer
dann
while( getchar()!='\n' ); -> ignoriert Lesefehler und EOF
und beides gleichzeitig verwenden sie dann im Beispielcode.
'vor der ersten Eingabe' soll man schon den Eingabepuffer auf diese Weise löschen, was unsinnig ist, da der
Anwender hierbei ein zusätzliches '\n' eingeben muss, BEVOR er die erste Eingabe machen kann.

Schon der erste Versuch, auf plattformabhängige Dinge hinzuweisen, geht schief:
"Rückgabewerte von main()" liefern unter Unix und MS-DOS unterschiedliche Ergebnisse
Unix: 0 = erfolgreich
sonst = Fehlernummer
"In der MS-DOS Welt verhält es sich mit den Rückgabewerten genau umgekehrt. Es wird 0 zurückgegeben, um einen Fehler zu signalisieren, während 1 bedeutet, dass das Programm erfolgreich terminiert hat."
Das ist falsch, MS-DOS/Windows verhalten sich genauso wie Unix, 0 zeigt fehlerfrei an, sonst fehlerhaft.
...
"Unter Windows ist der Rückgabewert schlicht belanglos und kann nicht abgefragt werden."
Das ist beides totaler Unsinn,
'programm && echo OK || echo Fehler' funktioniert in der Konsole sowohl unter Unix UND wie unter MS-DOS,
der Rückgabewert kann auch unter MS-DOS/Windows mit %ERRORLEVEL% abgefragt werden, die Behauptungen der Autoren
sind einfach nur falsch und zeugen von grundsätzlichem Unverständnis im Umgang mit C-Programmen, die sehr wohl
mit EXIT_SUCCESS bzw. EXIT_FAILURE die Fälle berücksichtigen und zwar UNABHÄNGIG von der Plattform.
Die Autoren verwenden selbst EXIT_SUCCESS, aber wohl ohne sich über den Sinn dieser Konstante Gedanken zu machen.
C99 schreibt (durch implizites return 0; in main()) sogar vor, dass 0 im Erfolgsfall aus main() zurückgegeben wird, also EXIT_SUCCESS == 0.

"Der Rückgabewert von main() ist betriebssystemabhängig" ist also wiederum falsch, bei return 0; wird immer 0 zurückgegeben, da ist nichts "abhängig".

Durchgängig präsentieren die Autoren die Beispielprogramme mit
main
{
}
schreiben aber erst auf Seite 139:
"Da ... in den meisten Beispielen in diesem Buch der Rückgabewert nicht benötigt wird, wird die Funktion in diesem Buch absichtlich ohne Rückgabewert definiert"
Das ist ebenso Unsinn, im dem Fall fügt der Compiler gemäß ANSI C Standard ein int als Returntyp hinzu (implizit int) und es wird immer ein Wert zurückgegeben (zufälliger Wert wenn return fehlt). (ab C99 wird bei Fehlen von return in main() immer return 0; ergänzt, und ab C99 ist main() ohne Return-Typ nicht mehr zulässig.
Der von den Autoren offenbar beabsichtigte Fall ohne Rückgabewert wäre void main(), dieser ist aber bei keinem
C Standard gültig.
Der Leser wird also vom Beginn des Buches an im Unklaren darüber gelassen, was es mit implicit int und main() auf sich hat, er muss bis Seite 139 lesen um diese Erklärung zu finden, dass ist für ein Lehrbuch und auch für den Gebrauch des Buches als Nachschlagewerk untragbar.

Arrays werden von den Autoren als Felder bezeichnet und auch hier misslingt der Ausblick auf C99 völlig:
Der Begriff VLA (variable length array) wird nicht genannt, ebenso wird keinerlei Beispiel gebracht oder die vorige Erklärung der Autoren zu sizeof für VLA erweitert.

Während die Autoren die VLA ab C99 wenigstens noch vage nennen, 'verschweigen' sie die restlichen Neuerungen in C99 für Felder(Arrays) offenkundig wieder aus Unwissenheit, indem sie behaupten:
"Bei Initialisierung von Feldern ist ein Überspringen von Elementen ist nicht möglich" -> falsch, ab C99 sehr wohl möglich

Im Kapitel Such/Sortierverfahren fehlt der Hinweis auf die Standardfunktionen bsearch+qsort stattdessen werden eigene Implementierungen gezeigt, selbst bei der Eigenimplementierung Quicksort wird niemals die qsort-Funktion aus der Standardbibliothek genannt.

Beim "Freigeben von Speicher" erfolgt der untaugliche "Tipp", mögliche Mehrfachfreigaben desselben Zeigers explizit zu "verhindern" mit:
if (db)
{
free(db);
db = 0;
}
Hierbei wird die Möglichkeit verschenkt, fehlerhaftes Programmdesign zu erkennen, da Mehrfachfreigaben desselben Speichers sehr oft zu Exceptions führen, die damit nicht mehr auftreten und fehlerhaftes Design nicht mehr erkannt werden kann.

Im ersten (und einzigen) größeren Beispielprogramm verwenden die Autoren laienhafte globale Variablen, obwohl sie selbst zuvor davor gewarnt haben.

Fazit:
Die Autoren begreifen nicht die Wichtigkeit der C-Standards, gerade für Einsteiger und in einem Lehrbuch ist die ausführliche und konsequente Verwendung des Standards als größter gemeinsamer Nenner aller Compiler wichtig.
Die permanenten einschränkenden Hinweise der Autoren in Beispielcode und Erläuterungen verwirren den Einsteiger, er wird durch die vielen compilerabhängigen Beschränkungen und Voraussetzungen abgelenkt von den eigentlichen Grundlagen von C, und auch diese werden oftmals falsch und sehr lückenhaft präsentiert.
Die Autoren sind in ihrer 3.Auflage des Buches, trotz ihrer 'langjährigen Programmiererfahrung' und trotz 'Redigierungen vieler Studierender' nicht in der Lage, ein brauchbares Lehrbuch zu präsentieren.
Für die angesprochenen 'erfahrenen Programmierer' ist das Buch sinnlos.
Das Buch ist veraltet und bietet keinesfalls die versprochene Einführung in 'komplexe Aufgaben' und keinesfalls die versprochene 'fundierte Behandlung der Sprache'.
Das Buch ist niemandem zu empfehlen.
Kommentar Kommentare (2) | Kommentar als Link | Neuester Kommentar: Jun 25, 2015 12:06 PM MEST


C/C++: Das umfassende Lehrbuch (Galileo Computing)
C/C++: Das umfassende Lehrbuch (Galileo Computing)
von Ulrich Kaiser
  Gebundene Ausgabe
Preis: EUR 39,90

7 von 12 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen Oberflächlich, lückenhaft, fehlerhaft, unbrauchbar, 27. Januar 2015
Verifizierter Kauf(Was ist das?)
Die habilitierten Autoren empfehlen ihr Werk für Schule, Studium und Beruf. Leser ohne Vorkenntnisse sollen auf ein professionelles Niveau der C und C++ Programmierung geführt werden. Eindrucksvolle Beispiele + durchdachte Programmieraufgaben soll das Buch enthalten, es wurde 'mit großer Sorgfalt geschrieben, geprüft und produziert'.
Nichts davon können die Autoren einhalten, das Buch ist ein gescheiterter Versuch der Autoren, mit eigenen laienhaften Vorstellungen den Leser zu 'professionellen Programmen' zu führen.
Der Leser ist keinesfalls nach Lektüre dieses Buches in der Lage, professionelle Programme zu entwickeln. Dafür ist das hier vermittelte Wissen zu fehlerhaft und zu lückenhaft. Der Umfang des Buches (1220 S.) stellt kein Qualitätskriterium dar.

Am Beginn des Buches versprechen die Autoren "keine Vorgriffe auf Stoff späterer Kapitel", was sie aber z.B. bei den Begriffen Anweisung, Codeblock, boolsche short circuit und void main() nicht einhalten (Begriff wird erwähnt, erklärendes Kapitel erfolgt später ohne zuvor darauf hinzuweisen; der Leser wird irritiert, da er zuvor nicht wissen kann, dass die Erklärung später folgt). Ebenso soll das Buch für Windows und Linux geeignet sein, plattformspezifische Unterschiede werden an keiner Stelle im Buch genannt.

Im C-Teil werden die üblichen Anfängerfehler gemacht, grundlegende Begriffe undefiniertes, unspezifiziertes und implementierungsabhängiges Verhalten bleiben unerwähnt:
- void main() -> kein Standard; wird erst auf Seite 635 erwähnt ("ein C Compiler akzeptiert void main(), aber der Standard sieht für das Hauptprogramm eine andere Schnittstelle vor"), nachdem die Autoren zuvor ausschließlich diesen Standardverstoß in ihren Beispielcodes begehen
- "%d" für Pointer und size_t
- Datentyp size_t wird nie genannt (auch nicht bei sizeof-Erklärung)
- fflush(stdin) -> kein Standard, funktioniert nur unter Windows
- konkrete Bytegrößen für float/double/long double genannt (obwohl der Standard keine Aussagen dazu macht) 1/2/4 und dann in der Folge wieder anders 4/8/8
- die Zeichenfolge 'a'...'z' wird als kontinuierlich vorausgesetzt -> vom Standard nicht garantiert
- srand(12345); -> unsinnige Verwendung mit konstantem Wert

for(;;)
{
fscanf(pf,"%s",token);
if(feof(pf))
break;
}
Auch hier scheitern die Autoren bei simplen Lesen von Strings aus einer Datei; neben dem umständlichen Coding provozieren sie Speicherüberläufe (bei längeren Strings) und Lesefehler bleiben ebenso unberücksichtigt.

- char haufen[5]="TEWR"; -> Zeichenketten-Initialisierung erfolgt ohne Hinweis auf die sichere Variante char haufen[]="TEWR";
- 1<<n -> kein Hinweis auf Überlauf und Vermeidung durch 1UL<<n
- fopen subspecifier "x" wird falsch erklärt und unerwähnt, dass erst in C11 definiert
- union wird als Aggregattyp vorgestellt -> falsch, ist kein Aggregattyp
- enum "welche Zahlenwerte dabei zugeordnet werden, ist nicht festgelegt" -> kompletter Unsinn, enum-Elemente besitzen immer einen definierten Wert
- für scanf fehlt die Erklärung der Formate
- malloc-Cast
naive Erklärungsversuche: 'lassen sie sich durch den Cast nicht verwirren, die Typanpassung ist formal erforderlich, damit der Returnwert der Funktion malloc zum Datentyp unseres Zeigers passt und zugewiesen werden kann...wenn Sie die Typumwandlung weglassen, erhalten Sie allenfalls einen Warnhinweis auf nicht kompatible Zeigertypen'
Hier offenbart sich wieder das naive Grundlagenunverständnis der Autoren, 'zugewiesen werden kann' in C ein void* Zeiger immer zu jedem anderen Datenzeiger und das ohne Warnhinweis des Compilers, die Autoren verwechseln hier das Typkonzept von C mit C++.
An anderer Stelle behaupten die Autoren wiederum völlig laienhaft, dass ein "Zeiger-Cast immer ohne Informationsverlust" sei, was ebenso Unsinn ist.
- "beim Array bleiben nicht angesprochene Felder uninitialisiert" -> falsch, static Arrays sind immer ganz initialisiert, endende nicht angesprochene Felder nach zuvor initialisierten Felder sind ebenfalls gemäß Standard initialisiert

Schwierigkeiten haben die Autoren ebenfalls beim grundlegenden Thema Array/Zeiger, nachdem sie uncompilierbaren Code zeigen:
int zaehle(char string[])
{
int a;
for(i=0,a=0; *string[i]!=0; i++) -> falsch, uncompilierbar

geben sie 2 Codevarianten für dasselbe Verhalten an
int zaehle(char string[])
{
int a;
for(i=0,a=0; string[i]!=0; i++)

int zaehle(char *string)
{
int a;
for(i=0,a=0; *string!=0; i++)

Die Autoren begreifen einfach nicht die völlige Äquivalenz von Array und Zeiger als Funktionsparameter, indem sie einmal die Array-Schreibweise und einmal die Zeiger-Form verwenden.

- int (*fz1)(); -> wird von den Autoren falsch als
"Zeiger auf parameterlose Funktion" bezeichnet und
"einem Funktionszeiger kann die Adresse einer beliebigen Funktion zugewiesen werden, deren Schnittstelle mit der bei der Definition des Zeigers angegebenen Schnittstelle übereinstimmt"; hier ebenso wieder Unverständnis der Autoren bei Grundlagen, fz1 ist ein Zeiger auf Funktion mit int-Returnwert und unbekannter aber fester Anzahl von Parametern, fz1 kann somit einer Vielzahl von Funktionstypen zugewiesen werden
- const int x = 4711;
"Konstanten haben natürlich keine Adresse, sodass der Adress-Operator nicht auf Konstanten angewandt werden kann." -> ein weiterer Tiefpunkt in den Erklärungsversuchen der Autoren, selbstverständlich haben auch konstante Objekte immer eine Adresse, über die sie z.B. auch per Pointer ansprechbar sind (lesend), die Autoren haben auch das Pointerkonzept von C nicht verstanden, wenn sie es als "natürlich" ansehen, dass Objekte keine Adresse haben.
Bei diesem Codebeispiel wäre es auch passend gewesen, gleich auf die Unterschiede im Verhalten von C und C++ bzgl. const hinzuweisen, das Wissen bleibt dem Leser ebenso vorenthalten.

Im (weitaus kleineren) C++ Teil des Buches unterbleiben folgerichtig auch sämtliche Hinweise der Autoren zu den Standards (C++98/03/11/14), während sie im C Teil wenigstens noch 1x den ANSI-Standard erwähnen (und auch dagegen verstoßen indem sie z.B. den Typ long long und Zeilenkommentare // verwenden) 'vergessen' sie auch darauf hinzuweisen, welchen Standard sie einsetzen, und auch hier wird mehrfach gegen z.B. C++98 verstoßen indem auto specifier verwendet wird aber nicht auf C++11 verwiesen wird.
Demzufolge unterbleiben auch Hinweise zu Neuerungen aus C++ - Standards nach C++98, wie unordered_map (Hashtables), Smartpointer, range-based for, Lambdas...

Unterschiede von C++ zu C werden ebenso nicht erklärt ( const (Compilezeit/Runtime), automat. enum-Bereichsprüfung beim Zugriff, typedef/using ), dafür werden naiv "Erweiterungen" von C++ gegenüber C aufgezählt, fast alle falsch:
- bool, true, false -> ab C99 vorhanden
- Vorwärtsverweise von struct -> in C vorhanden
- neue Schreibweisen für Operatoren &&(and) ||(or) usw. -> ab C95 vorhanden

Die Autoren verwenden exzessiv friend (obwohl sie selbst davor warnen) genauso wie string+stack in eigenen Codebeispielen (Kollision mit gleichnamigen STL-Containern), vergessen delete nach new und geben auch die C++ Operatortabelle nicht an (die sich von C unterscheidet).
Bei den Typ-Casts 'vergessen' die Autoren dynamic_cast, dafür füllen sie die STL-Container-Kapitel jeweils mit einer (identischen) Erklärung des Iterators, und wie man ihn anwenden soll, ebenso wie sie Funktion statt Methode bei Klassen einsetzen.
Der Leser wird permanent durch Wiederholung von bereits vorgekommenen Stoff genervt, das gilt u.a. für Konstruktor/Destruktor/virtual, die auch mehr als 2x vorgestellt werden um dann beim 3. Mal auch endlich die Destruktor-virtual Besonderheiten zu nennen.

Einige Einsicht zeigen die Autoren dann erst am Ende des Buches (bei set,multiset):
"Auch für Mengen gibt es die Funktionen size und empty, auf die ich jetzt aber nicht noch einmal eingehe. Auch das Konzept der Iteratoren kennen Sie bereits von anderen Containern".

Im letzten Kapitel schreiben die Autoren: "Sollen Eigenschaften abgeleiteter Klassen im Container erhalten bleiben, ist es sinnvoll, anstelle der Objekte nur die Zeiger auf die Objekte im Container zu verwalten" um dann den 'Nachteil' festzustellen: "Da wir nur den Zeiger auf das Objekt in den Container kopieren, kann der Container nicht mehr das Speichermanagement ... übernehmen". Hierbei den Leser NICHT auf Deep-Copy nebst Beispielimplementierung hinzuweisen ist schon nicht mehr fahrlässig sondern einfach nur inkompetent, die Autoren beschreiben nur lapidar "der Entwickler muss sich selbst kümmern". Sowas lässt den Leser allein mit seinen Fragen und ist absolut sinnfrei in einem Lehrbuch.

Fazit:
Die Autoren sind mit ihrem angekündigten Versuch, ein Buch für Schule, Studium und Beruf bis zur Erstellung professioneller Anwendungen zu präsentieren komplett gescheitert.
Ihre '5.aktualisierte und überarbeitete Auflage' ist voller Fehler und Lücken, die häufigen falschen Behauptungen zu Grundlagen, das Ignorieren der C und C++ Standards ist einfach nur peinlich.
Das Werk ist nicht wie angekündigt 'umfassend' sondern nur eine Offenbarung der eigenen naiven Vorstellung von 'professioneller' Programmierung.
Niemand wird anhand dieses Buches professionelle Anwendungen erstellen können, und auch alle Einsteiger werden durch das vermittelte falsche Grundlagenwissen, unsinnige Behauptungen, die fehlerhaften und standardinkonformen Beispielcodes in die Irre geführt.

Das Buch ist niemandem zu empfehlen.
Kommentar Kommentare (7) | Kommentar als Link | Neuester Kommentar: May 31, 2015 5:48 PM MEST


Eine praktische Einführung in C: Lern- und Arbeitsbuch für Programmiereinsteiger
Eine praktische Einführung in C: Lern- und Arbeitsbuch für Programmiereinsteiger
von Doina Logofatu
  Broschiert
Preis: EUR 29,90

2 von 6 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen Oberflächlich, fehlerhaft, unbrauchbar, 21. September 2014
Die studierte Informatiklehrerin und Autorin 'diverser,sehr erfolgreicher IT-Bücher' richtet sich mit ihrem als Lern- und Arbeitsbuch konzipierten Werk an Programmiereinsteiger.
Anhand einer Vielzahl von Problemen möchte sie dem Leser die Programmiersprache C näherbringen.
Die Probleme, d.h. es handelt sich überwiegend um Aufgabenstellungen aus dem Bereich der Mathematik (ggT, Primzahlen, goldener Schnitt, lineare Rekurrenz, Goldbachsche Vermutung, Fraktale usw.), werden zunächst als Lösung präsentiert, anschließend erfolgt eine Erklärung der neuen C-Sprachmittel und Funktionen.
Die Autorin orientiert (mit einer Ausnahme, für Fraktale nutzt sie BCC) ausschließlich auf den Compiler MSVC++ 2005 Express und Windows als Plattform.
Die gezeigten Programme sollen sich an den ANSI-C-Standard halten und mit jedem Compiler funktionieren.

Das ist vollständig misslungen.
Die Erklärung der Grundlagen der Sprache C gerät viel zu kurz und ist fehlerhaft.
Grundlegende Fachbegriffe werden nicht genannt und erklärt und die genannt werden, werden oft falsch erklärt; gerade für ein Einsteigerbuch inakzeptabel.
Ständig hat man den Eindruck, dass die offensichtlich stark mathematisch fokussierte Autorin den trockenen Theorie-stoff möglichst schnell hinter sich bringen möchte um endlich die 'wahren', d.h. nahezu ausschließlich mathematischen Probleme zu lösen.
Das beginnt mit den Schlüsselwörtern: die Autorin nennt die Anzahl 32, zählt dann in der folgenden Tabelle aber 37 auf (inkl. der 5 neuen in C99, die vom genannten Compiler nicht unterstützt werden).
Weiterhin passieren Fehler, indem die Autorin für die Funktionsdeklaration den Pre-ANSI K&R-Style

[DatenTyp] Funktionsname([Liste der Formalparameter])
[Deklaration der Parameter]

nennt, statt den in ANSI C definierten (den sie selbst ausschließlich benutzt).
Misslungen ist auch die Erklärung einer Zuweisung bei Datentypen:
"In der Evaluierung des Ausdrucks verwendet man die Regel der expliziten Umwandlung: Wenn sich der Typ des Ausdrucks rechts vom Gleichheitszeichen vom Typ des Ausdrucks links davon unterscheidet, dann wird der Wert des rechten Ausdrucks in den linken Typ umgewandelt und danach findet die Zuweisung statt."
Die Autorin bringt hier explizite und implizite Typumwandlung durcheinander.
Was passiert bei solchen Umwandlungen nichtkompatibler Typen?
In diesem Zusammenhang muss dem Leser erklärt werden, was inkompatible Typen sind, ebenso wie der Begriff undefiniertes Verhalten.
Weitere Fehler passieren wie:
- Verwechslung von Deklaration mit Definition
- globale Variablen sind überall sichtbar -> falsch, nicht zwischen Modulen (ein Programm aus mehreren C Quelldateien kommt nirgends vor)

Bei der Vorstellung der Datentypen werden die üblichen Anfängerfehler gemacht, es werden konkrete Bytegrößen der Typen genannt (die im Standard nicht festgelegt sind), char wird mit signed char gleichgesetzt.
Die Vorstellung von Bibliotheksfunktionen misslingt ebenfalls,
bei printf/scanf werden die Formatierungen zusammen in einer Tabelle dargestellt, sodass der Leser davon ausgehen muss, diese wären gleich, was nicht der Fall ist.
Hierbei wird "%lf" für printf und double dargestellt (erst ab C99), long double wird komplett 'vergessen', width+precision wird gar nicht erwähnt, ebenso wie der return-Wert bei scanf.
Da die Autorin in nahezu jedem Beispielprogramm eine Eingabe mit scanf verwendet, ist für den Leser sowohl die Längenbegrenzung für string mit <width> wie auch die Auswertung von korrekten Eingaben über den return-Wert von scanf unverzichtbar, unterbleibt aber offenbar aus Unkenntnis der Autorin im gesamten Buch.
- include-Files "alloc.h"+"malloc.h" werden gezeigt -> kein ANSI C Standard
- fcloseall wird genannt und vielfach verwendet -> kein ANSI C Standard
- gets wird verwendet -> ohne Erklärung und ohne Hinweis auf Fehler
- bei fopen wird die Option "t" genannt und verwendet -> kein ANSI C Standard
- stricmp/strnicmp -> kein ANSI C Standard
- void main() -> kein ANSI C Standard
- unnötiger Cast bei malloc
- sinnfreier und falscher Cast bei strlen: (int) strlen(...)
- "%ld" für unsigned long statt korrekt "%lu" im gesamten Buch

Bei <union> wird behauptet "es gibt keine Möglichkeit zu erfahren, welche Komponente gerade aktuell ist, also zuletzt gesetzt wurde", was falsch ist. Es gibt eine standardgemäße Möglichkeit.

Konkrete Implementierungen sind fehlerhaft:

char name[15]; /* deklariert Zeichenkette */ statt definiert ...
scanf("%s",name); -> UB für Strings > 14

- feof wird direkt nach fopen verwendet
- compare-Funktion bei qsort/bsearch verwendet fehlerhaft eine Subtraktion
- atol wird nochmal explizit mit gleichem Namen selbst implementiert -> sinnfrei in einem Einsteigerbuch
- fclose(f) wird für zuvor evtl. fehlerhaft geöffnete Datei aufgerufen -> Exception

char tagName[7][10]={"Donnerstag","Freitag"};
Laienhafte Implementierung von initialisierten Stringlisten -> UB wegen Zugriff auf undefinierten Speicher

Grundbegriffe werden falsch dargestellt,
typedef struct nodehash {
TListe *liste;
struct nodehash *next;
} THashTable;
wird als Hashtable bezeichnet, in einem wilden Beispielprogramm, indem diese verkettete Liste von verketteten Listen mit einer Hashfunktion " nr % 10 == 0 " befüllt wird. Anschließend erfolgt im Programm gar kein Einzelzugriff mehr auf die Elemente (Grundprinzip einer Hashtable) sondern nur der Gesamtinhalt durchlaufen. Dem Leser wird der Grundbegriff Hashtable falsch erklärt, er wird in die Irre geführt.

Fazit:
Die Autorin ist mit ihrer 'praktischen Einführung in C' gescheitert.
Abgesehen von den vielen mathematischen Aufgabenlösungen ist die Einführung in die Sprache C für den Leser unbrauchbar, laienhaft, oberflächlich, fehlerhaft, inkonform zum genannten ANSI C Standard und irreführend.
Im ganzen Buch erfolgt keinerlei Fehlerbehandlung für Nutzereingaben.
Das Buch ist niemandem zu empfehlen.
Kommentar Kommentar (1) | Kommentar als Link | Neuester Kommentar: Feb 20, 2015 1:13 PM CET


Einstieg in C: Für Programmiereinsteiger geeignet (Galileo Computing)
Einstieg in C: Für Programmiereinsteiger geeignet (Galileo Computing)
von Thomas Theis
  Broschiert
Preis: EUR 24,90

7 von 12 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen Naiv, fehlerhaft, widersprüchlich, unbrauchbar, 31. August 2014
Der studierte Informatiker und Autor 'zahlreicher erfolgreicher Fachbücher' wendet sich mit seinem Buch direkt an Programmierneulinge, 'schnell und einfach' sollen sie damit C lernen.
Schnell und einfach erlernt niemand die Sprache C.
Es ist ein Trugschluß des Autors, vom relativ geringen Sprachumfang und Bibliothek auf einfaches Erlernen zu schlussfolgern, der Autor verspricht hier Falsches, die wenig fundierten Kenntnisse des Autors tragen ebenfalls nicht zur Kompetenz als Lehrbuch bei.
Das Buch ist misslungen.
Ohne Vorkenntnisse soll der Leser loslegen können.
Demzufolge beginnt der Autor bei Adam und Eva: "Das Zeichen { geben sie über die Tastatur ein durch Drücken der Kombination AltGr+{".
Der Autor orientiert nahezu ausschließlich auf Dev-C++ als IDE und Windows als Plattform.
Dass Dev-C++ ausschließlich eine IDE ist und kein Compiler erwähnt der Autor nicht, für ihn ist Dev-C++ der Compiler und hier beginnt schon die Irreführung des Lesers.
Zitat: "Dev-C++ setzt einige aber nicht alle Vorgaben von C99 um"
Dev-C++ enthält als Compiler MinGW, eine Windows-Portierung von gcc. Diesen einfachen Sachverhalt 'vergisst' der Autor, dem Leser mitzuteilen. Dass gcc schon viele Jahre den C99-Standard unterstützt und dafür nur die entsprechende Option (-std=c99) in der IDE eingestellt werden muss, 'verschweigt' der Autor.

Die Erklärungsversuche des Autors für gängige C Fachbegriffe misslingen völlig,
- Anweisung + Ausdruck werden sofort und ohne Erklärung verwendet
- Stringliterale werden als "Text" bezeichnet
- statt des allseits üblichen "int main(int argc,char *argv[])" verwendet der Autor "int main(int anzahl, char *worte[])"
All dies trägt nicht zum Wiedererkennungswert für den Leser bei, falls er sich mal außerhalb dieses Buches mit C-Programmierung beschäftigt.

Viele andere Anfängerfehler präsentiert der Autor in seinem Werk,
- Verwechselung von Deklaration mit Definition
"Variablen erhalten bei Deklaration einen Wert" -> nur bei einer Definition ist dies möglich
- Verwechselung von Parameter und Argument
- bei Subtraktion zweier Zeiger verwendet der Autor nicht das standardkonforme ptrdiff_t sondern int als Ergebnistyp
- kein Hinweis zu Besonderheiten bei Gleichheitsoperatoren mit floating point Variablen
- "main() kann auch vom Typ void sein" -> nicht standardgemäß (außerdem ist void kein 'Typ')
- der Autor geht von kontinuierlicher Folge der Alphabet-Buchstaben im ASCII-Zeichensatz aus -> nicht garantiert durch den C Standard
- "mit C99 wurde long double neu eingeführt" -> falsch, der Typ ist bereits seit C89 vorhanden
- die Konstante M_PI wird verwendet -> nicht im Standard vorhanden, sondern nur eine Compiler-Erweiterung
- "strlen liefert einen Wert des Datentyps unsigned long" -> richtig ist size_t
- unnötiger Cast bei malloc
- bei realloc wird keine Fehlerprüfung gezeigt, wieder ignoriert der Autor den return-Wert von Funktionen
Stattdessen zeigt der Autor ständig im Buch den sinnfreien (und fehleranfälligen) Cast bei strlen:
int aLaenge = (int)strlen(a);
Hierbei wird explizit eine mögliche Compilerwarnung durch den Cast unterdrückt (unsigned zu signed Wert), inakzeptabel gerade für ein Einsteigerbuch.

Reichlich naiv sind die Vorstellungen des Autors zum Sinn des C Standards:
"Der beschriebene Ablauf erweist sich unter den verschiedenen Betriebssystemen und Entw.umgebungen als erfolgreich und frei von Fehlern und Warnungen. Dies ist bei Nutzung der Funktionen fgets() (zum Einlesen) und fflush() (zum Löschen des Eingabepuffers) nicht der Fall."
Hier zeigt sich das grundlegende Unverständnis des Autors zu C: er begreift nicht, dass die Intention genau in einer PlattformUNabhängigkeit liegt, und Sprach- und Bibliotheksumfang vom Standard in der Form genormt sind, dass keinerlei Anpassungen am Quellcode vorgenommen werden müssen, wenn ausschließlich Standardfunktionen benutzt werden.
Standardfunktionen pauschal anzuzweifeln ohne den Leser konkret ("fflush(stdin)") auf die entsprechenden Vorgaben aus dem C-Standard hinzuweisen, ist fahrlässig und suggeriert dem Einsteiger, der Gebrauch der Standardbibliothek wäre unsicher. Spätestens hier war es notwendig, den Leser auf den Fachbegriff "undefiniertes Verhalten" hinzuweisen, Hinweise darauf und auf andere elementare Fachbegriffe unterbleiben im gesamten Buch.
Das Buch ist somit nicht nur ein Missverständnis sondern ein grundlegendes Missverständnis; der Autor ist nicht in der Lage, dem Leser diese Grundlagen zu vermitteln.

Inkonsequent beschreibt der Autor zunächst für User-Eingaben:
"... auf die Prüfung der Eingabewerte bei scanf u.ä. wurde zunächst verzichtet, wir gehen davon aus, dass alle Eingaben richtig erfolgen..."
das ist insofern inkonsequent, dass dem Einsteiger hier zunächst die Möglichkeiten der Standardbibliothek vorenthalten werden, nur um diese dann anschließend in einem Kapitel kurz zu präsentieren, um aber anschließend in den umfangreicheren Beispielcodes wieder auf sie zu verzichten;
der Einsteiger muss bei Lektüre des Buches ohne diese versteckte Ankündigung gelesen zu haben davon ausgehen, dass die gezeigten Beispielcodes 'praxisnahes' C sind, wie der Autor zu Beginn ankündigt.

Die vom Autor dann präsentierten 'sicheren' Varianten zur typgerechten Eingabe sind dann auch folgerichtig wenig brauchbar, da auch wieder inkonsequent:
der Autor präsentiert fgets+atoi/atof für int/double-Eingabe, 'verzichtet' also offensichtlich aus Unwissenheit auf sscanf bzw. fgets+strtol/strtod, die eine echte Fehlerauswertung ermöglichen, während atoi+atof bei Fehlern ausschließlich mit 0 antworten, hier also dem Einsteiger keine Möglichkeit gegeben wird, eine fehlerfreie von einer fehlerhaften Eingabe zu unterscheiden, z.B. führen atoi("0") und atoi("äöü") zum gleichen numerischen Ergebnis, ein Fehler ist somit nicht erkennbar.
Ebenso zeigt der Autor nicht die Längenprüfung bei Eingabe von Strings:

char puffer[255];
scanf("%s",puffer); /* statt scanf("%254s",puffer); */

Bei qsort wird der übliche Anfängerfehler begangen, indem die compare-Funktion mittels Subtraktion implementiert wird, was bei Werten an den Bereichsgrenzen zu Fehlern führt.

Auch bei simplen Array-Initialisierungen scheitert der Autor
int array[3] = {1,2,3};
statt
int array[] = {1,2,3};
Auch als 'Tipp' ist dieses praxisübliche Verfahren der sicheren Array-Initialisierung nicht im Buch zu finden.

Für size_t Werte bei printf verwendet der Autor ausschließlich "%lu", ohne den üblichen und notwendigen Cast (unsigned long),
printf("%lu",sizeof(...));
statt korrekt
printf("%lu",(unsigned long)sizeof(...));
Offensichtlich glaubt der Autor auch hierbei, wenn keine Compilerwarnung erscheint, wären keine Fehler vorhanden, weil seine aktuelle Compilerimplementierung size_t als unsigned long vorsieht, was aber für andere Compiler nicht gelten muss. Der Autor hat nicht verstanden, warum dieser Cast notwendig ist, um portabel zu bleiben; diese Verständnislosigkeit des Autors zu C Grundlagen durchzieht das gesamte Buch.
Den ab C99 konformen Weg über "%zu" für size_t bei printf 'verschweigt' der Autor wiederum.

Bei der Dateibehandlung wird die Funktion stat() aus sys/stat.h gezeigt ohne Hinweis, dass sie nicht im C Standard vorkommt, ebenso wird chmod() verwendet und auch hier wieder ohne Auswertung der fehlerfreien Ausführung über den return-Wert. (insbesondere bei Unix relevant, wo die Rechteverwaltung für Dateien sehr viel restriktiver ist als bei Windows)

opendir/readdir/closedir aus dirent.h werden gezeigt, wieder ohne Hinweis darauf, dass dies keine Standard-Funktionen sind und unter Windows z.B. bei Verwendung von VisualStudio nicht vorhanden sind, sondern nur als gcc-Extension.
Dasselbe gilt für das genannte gettimeofday.

Die einfachsten Codebeispiele misslingen, z.B. beim simplen Schließen einer Datei im Fehlerfall:

FILE *file = fopen("datei.csv","r");

if( file==NULL )
printf("Datei konnte nicht geöffnet werden.");
...
fclose(file); /* hier wird im Fehlerfall fclose(NULL) aufgerufen, was zum Programmabsturz führt */

Von 'praxisnaher' Einführung in C kann hierbei wie auch bei vielem Anderem keine Rede sein, der Leser wird irregeführt, die Beispielcodes sind falsch, unvollständig oder nicht standardkonform.

Im Anhang ist die Liste der Funktionen der Standardbibliothek nach Headerdatei gruppiert und nicht gesamt sortiert, das Suchen der Funktionen im Buch ist damit unbrauchbar; Header, die nicht zum Standard gehören, werden nicht entsprechend gekennzeichnet.

Fazit:
Der Autor ist unfähig, ein Lehrbuch für Einsteiger in C zu präsentieren.
Der Autor vermittelt C-Grundlagenwissen mehrheitlich falsch, inkonform zu Standard oder unterlässt Erklärungen ganz.
Das Buch ist widersprüchlich aufgebaut, je nachdem, welchen Teil des Buches der Leser aktuell liest, werden unterschiedliche Erklärungen und Beispielcode zum gleichen Thema gezeigt.
Dort, wo ein Cast wegen Portabilität hingehört, 'vergisst' der Autor ihn, dort wo kein Cast hingehört und sogar falsch ist, setzt er ihn, und das durchgängig im ganzen Buch: der Autor hat nichts verstanden, und gibt diese Verständnislosigkeit an den Leser weiter.
Für einen Autor 'zahlreicher erfolgreicher' Fachbücher ist diese Präsentation für den Einstieg in C nur noch peinlich zu nennen.
Der Autor verfügt selbst nur über naive Grundkenntnisse in C, von den versprochenen 'Praxistipps aus dem Programmieralltag' kann KEINE Rede sein.

Das Buch ist unbrauchbar und auch für Einsteiger nicht zu empfehlen.
Kommentar Kommentare (5) | Kommentar als Link | Neuester Kommentar: Feb 20, 2015 1:14 PM CET


Softwareentwicklung in C (Xpert.press)
Softwareentwicklung in C (Xpert.press)
von Klaus Schmaranz
  Taschenbuch
Preis: EUR 49,95

7 von 9 Kunden fanden die folgende Rezension hilfreich
1.0 von 5 Sternen Naiv, fehlerhaft, inkompetent, unbrauchbar, 18. August 2014
Der promovierte Autor lehrte 2001 an der TU Graz, sein Werk entstand damals nach seinen eigenen Worten aus einem Vorlesungsscriptum.
Gleichzeitig möchte er die strukturierte Designphase in den Vordergrund stellen, auf das Warum bei Problemen eingehen und das Gelernte soll sofort direkt in der Praxis einsetzbar sein.
Mit all diesen Anliegen scheitert der Autor kläglich, bedingt dadurch, dass er selbst trotz eigener "16-jähriger Entwicklungspraxis" nur über ein naives Grundverständnis für das Anliegen der Programmiersprache C verfügt.
Der Autor ist nicht in der Lage, den C-Standard zu präsentieren, weder C89 noch C99 bilden die Grundlage seines Buches, C99 hat 2001 bereits existiert und wurde vom gcc unterstützt.
Die Beispielcodes sind ein wildes Durcheinander von C89 und gcc-Extensions, der Autor gibt sich noch nicht mal die Mühe, seine eigenen in Anhang aufgeführten "Coding-Rules" einzuhalten,
- mal verwendet er main(), mal int main(), und vergisst dabei schon mal das in C89 notwendige return 0; am Ende von main
- Blockkommentare /* */ soll man prinzipiell nicht verwenden sondern ausschließlich // , da der Zeilenkommentar sicherer sei -> es ist genau umgekehrt
- keine globalen Variablen -> sehr sinnvoll, nur hält sich der Autor durchgängig nicht daran, z.B. verwendet er eine Funktion wie void run(void), die zwingend globale Variablen verwenden muss
- Variablen-Namenskonventionen mit Verstoß gegen den Standard werden vorgegeben (Unterstrich+Uppercase), z.B. _Coord_, _Rect_

Besondere Schwierigkeiten hat der Autor beim einfachen Thema Initialisierungen, hier macht er alles falsch, was nur falsch zu machen ist
- er behauptet, es gäbe für Variablen keinerlei implizite Initialisierungen -> falsch, sowohl globale wie static deklarierte oder endende, nicht explizit initialisierte struct-Elemente werden 0 initialisiert (all bits zero)
- er behauptet, alle Zeigervariablen sind NULL initialisiert
Zitat: "Per Konvention erfolgt die Initialisierung eines Pointers immer mit dem Wert NULL oder null."
(nachdem er ja kurz zuvor behauptete, es gäbe KEINE impliziten Initialisierungen und Zeiger wären ganz normale Variablen) -> falsch, Zeigervariablen sind nicht immer NULL initialisiert und mit null niemals; dieser 'Tipp' gipfelt in dem Hinweis, wenn man NULL in stdlib.h nicht findet, solle man in anderen Headern suchen, andernfalls auch NULL oder null selbst definieren mit (void*)0;
auch hier ignoriert der Autor aus Unkenntnis den Standard, der NULL IMMER (mind.) in stddef.h vorschreibt
- er behauptet, endende nicht explizit initialisierte struct-Elemente wären nicht initialisiert -> falsch, diese sind immer 0 initialisiert, ebenso bei Arrays
Ein Blick in den C-Standard hätte genügt, der Autor hat aber eben diesen Überblick nicht, sonst hätte er nicht solchen Unsinn behauptet, der nur davon kommen kann, dass der Autor in seiner 'langjährigen Entwicklungspraxis' ausschließlich Programmieren durch Ausprobieren des gcc im non-Standard-Modus praktiziert hat. Der Autor empfiehlt den gcc, nennt aber keine der umfangreichen Optionen dieses Compilers, auch nicht die standardkonforme Programmierung mit -ansi, -std=c99 oder die warning-levels.

Der Begriff C-Standard kommt nur 1x im Buch vor, und dann auch noch genau falsch herum:
"struct-Variablen können nicht als Parameter oder return-Values bei Funktionsaufrufen verwendet werden"
weil "nur manche Compiler ABWEICHEND vom C-STANDARD" dies erlauben, deswegen soll dieses "Feature" nicht benutzt werden -> absoluter Unsinn, es ist genau umgekehrt: <der C-Standard GARANTIERT, dass struct -Zuweisungen IMMER funktionieren>; dieser 'Tipp' des Autor ist komplett naiv,laienhaft und falsch, der Autor hat auch hierbei nichts verstanden.

An anderer Stelle offenbart sich dann der Autor beim Thema size_t:
'Ohne uns hier auf genauere Betrachtungen zum(speziell definierten, nicht Core-C) Datentyp size_t einzulassen...'
der Autor sieht sich also als "Core-C" Entwickler, der abseits der Sprachstandards arbeitet und lieber eigene Versuche macht;
auch hierbei greift er mehrfach fehl mit naiven Vorstellungen über Windows mit der Behauptung,
int c;
while( (c=getchar())!='\n' )
funktioniert nur unter Unix und NICHT unter DOS/Windows (weil dort statt LF ein CR+LF jedes Zeilenende kennzeichnet) -> es zeigt sich wieder naives Unverständnis zu C-Grundlagen; denn selbstverständlich 'funktioniert' dieser Code auch unter Windows, da die C-Funktionen der Windows-Runtimelib die standardgemäßen Schnittstellen entsprechend transparent machen, was Sinn und Zweck von standardisierten Bibliotheken ist (in diesem Fall gelten die Standard-Schnittstellen für textbasierte Streams und stdin (auf welchem getchar() arbeitet) ist als Textstream im C-Standard vorgegeben).

Als "wichtige Sicherheitsmaßnahme" hebt der Autor hervor, dass man den Pointer nach free(); immer NULL setzen solle,
damit es bei 'komplexen' Programmen nicht zu Mehrfachfreigaben mit Segmentation Violation kommen kann;
dass durch eine solche 'Sicherheitsmaßnahme' in Testläufen von 'komplexen' Programmen niemals die fehlerhaft implementierten Mehrfachfreigaben entdeckt werden können, erwähnt der Autor nicht und wieder zeigt auch hier wieder sein grundsätzliches Unverständnis im praktischen Umgang bei Entwicklung und Test von 'komplexen' Programmen.

Den Compiler und dessen Optionen zur statischen Codeanalyse zu benutzen, kommt dem Autor in seiner 'langjährigen Entwicklungspraxis' also nicht in den Sinn, obwohl er vollmundig verspricht:
"alle Beispiele im Buch sind so weit wie möglich an 'sinnvolle' Konstrukte aus dem Tagesgeschäft der SE angelehnt";
Eine Erklärung, inwieweit ein in die Lehre an einer TU eingebundener promovierter Mitarbeiter über 'langjährige' 'Praxis' in der Softwareentwicklung verfügen kann, bleibt der Autor schuldig.

Abschließend und offensichtlich als Füllmaterial für das Werk dienen Kapitel zu Unix-Tools wie grep und emacs, die der Autor auch den Lesern statt einer IDE empfiehlt.
Im Anhang fehlt eine sortierte Auflistung der Standard-Bibliothek, als Nachschlagewerk taugt das Werk auch nicht.

Der Autor hat aufgrund seiner naiven Vorstellung von 'praxis'orientierter Softwareentwicklung und Unkenntnis des C-Standard kläglich versagt, ein Lehrbuch für die "Softwareentwicklung in C" zu präsentieren.
Grundlagen von C werden falsch oder gar nicht dargestellt (undefiniertes Verhalten, sequence point, lvalue,...), die Beispielcodes sind absolut laienhaft.
Didaktisch ist das Werk ebenso unbrauchbar, der Autor widerspricht sich oft selbst und hält sich nicht an seine eigenen Code-Rules.
Der Autor offenbart grenzenlose Naivität und Ignoranz, er lebt als "Core-C" Programmierer in seiner eigenen Welt.
Das Buch ist veraltet, unbrauchbar und niemandem zu empfehlen.
Kommentar Kommentare (3) | Kommentar als Link | Neuester Kommentar: Feb 20, 2015 5:21 PM CET


C-Programmierung: Unter Linux, Unix und Windows
C-Programmierung: Unter Linux, Unix und Windows
von Helmut Herold
  Broschiert
Preis: EUR 39,90

4 von 15 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 static Variablen auch mit Nicht-Konstanten: static Variablen dürfen erst ab C99 auch nicht-konstant initialisiert werden, es fehlt der Hinweis auf C99
- 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, unter Windows werde das Linefeed '\n' durch \n\r (ASCII 10+13) ersetzt;
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 Kommentare (13) | Kommentar als Link | Neuester Kommentar: Feb 21, 2015 1:01 PM CET


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

26 von 34 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 (16) | Kommentar als Link | Neuester Kommentar: Dec 19, 2014 7:01 PM CET


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

25 von 27 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 verschiedene VCS als Git-Vorgänger 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 Variable 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 sizeof, 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 Kommentare (2) | Kommentar als Link | Neuester Kommentar: Feb 20, 2015 1:19 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

7 von 12 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 (6) | Kommentar als Link | Neuester Kommentar: Nov 4, 2014 8:00 AM CET


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

11 von 17 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ß (Taschenbuch)
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.
Kommentar Kommentare (4) | Kommentar als Link | Neuester Kommentar: Jun 8, 2015 9:34 AM MEST


Seite: 1 | 2 | 3