Archiv verlassen und diese Seite im Standarddesign anzeigen : C Progr.. warum Klammern
C Programmierung allgemein,
mir leuchtet es absolut nicht ein,
warum ich dauernd alles einklammern muss in C.
Bei einer boolschen Abfrage zum Beispiel:
if testflag
{
}
muss ich
if (testflag) schreiben.
oder if (x==1)
Was sollen denn da die Klammern. Das ändert weder mathematisch was, noch gäbe es irgendwelche anderen Interpretationen für den Compiler,
bin ich zumindest der Meinung. In Pascal oder Modula brauche ich das auch nicht.
Gibt für mich auch absolut keinen Sinn. Wie so vieles in C........
Siro
Besserwessi
29.10.2010, 16:01
Beim IF (....) gehören die Klammern einfach zu Befehl. Das soll wohl an den Aufruf einer Funktion erinnern, auch die meisten Compiler das intern wohl anders behandeln werden.
Die Geschweiften Klammern entsprechen ziemlich genau bei Pascal/Modula dem Begin und End. Die Klammern sind einfach nur schneller zu tippen. Wenn hinder dem If( ) nur ein Befehl kommt, kann man die { } auch weglassen.
Die Syntax bei C ist auch nicht immer sinnvoll, daran kann man aber nicht viel ändern. Das sind oft Altlasten.
:D Wenn du sonst keine Sorgen hast...
Gibt für mich auch absolut keinen Sinn. Wie so vieles in C........
Nur weil man etwas nicht versteht, muss es nicht schlecht sein!
Wenn ich so manches größere Programm in z.B. Bascom sehen, dann finde ich die C-Syntax sehr viel übersichtlicher!
... das ist eine gute Frage, ich progge schon sehr lange in Zeh und hab mir darüber noch nie Gedanken gemacht, weil das eben die Syntax ist.
Das ist so ne Art Frage wie, warum Endet ein Satz mit einem Punkt ?
Denk mal drüber nach, vielleicht ist if ja (wie) eine Funktion und die Übergabeparameter gehören eben in Klammern. for(;;) ist da je genauso.
C ist eben nicht dieses grauselige Basic. Dafür reichen dann auch {} statt Begin End IF - Murks ...
und das schönste ist immer noch
int hugo = peter < klaus ? 4 : 2;
Viel Spaß noch,
Vajk
oberallgeier
29.10.2010, 18:26
... In Pascal oder Modula brauche ich das auch nicht ...Und wo liegt jetzt die Begründung, dass man es deswegen in C nicht brauchen würdenkönntedürfteoderso
... dauernd alles einklammern muss in C ...Nach dem üblichen System der Syntaxregeln (die so der eine oder andere Compiler eingebaut hat) müsste ich jetzt sagen: es stimmt nicht. Du must nicht DAUERND einklammern - und schon garnicht alles. Beides wäre fehlerhaft . . . . so "denken" eben Compiler.
... noch gäbe es irgendwelche anderen Interpretationen für den Compiler ...Mal ne Frage: weißt Du soviel über Compiler, dass Du da ganz sicher bist? Vielleicht gar ein Compilerbauer? Also schon in den Anfängen logischer Propädeutik dürfte das geklärt worden sein (vermute ich). Oder andersrum - wolln wa uns mal jaans dumm ställn:
Du gehst spazieren mit Max und Gerti oder Kurt und Emil
Du gehst spazieren mit (Max und Gerti) oder (Kurt und Emil)
Du gehst spazieren mit Max und (Gerti oder Kurt) und Emil
obergeier: und gleich & oder und gleich &&
und was ist in deiner Spazierwiese bevorrechtigt: und oder oder und oder oder und ?
... also ich würde am liebsten nur mit Gerti spazieren gehen :-)
SprinterSB
29.10.2010, 18:34
mir leuchtet es absolut nicht ein,
warum ich dauernd alles einklammern muss in C.
Bei einer boolschen Abfrage zum Beispiel:
if testflag
{
}
muss ich
if (testflag) schreiben.
oder if (x==1)
Was sollen denn da die Klammern. Das ändert weder mathematisch was, noch gäbe es irgendwelche anderen Interpretationen für den Compiler,
bin ich zumindest der Meinung.
So ist eben die C-Syntax. Wo ist das Problem? Es gibt Sprachen, die sind noch viel plüschiger, siehe Ada.
Der Grund ist, daß eine solche Syntax leichter zu parsen ist.
In Pascal oder Modula brauche ich das auch nicht.
Gibt für mich auch absolut keinen Sinn. Wie so vieles in C........
Na dann nimm doch Pascal oder Modula wenn dir C nicht gefällt. Gibt doch Sprachen genug. Schreibs eben in Python oder Forth oder Intercal.
Oder nimm dir die GCC-Quellen und klöpple nen eigenen C-Dialekt nach deinem Gusto.
Ich würde aber drauf wetten, daß die Zeit, die du für die Implementierung eines Sonderlocken-C-Dialekts brauchst, dafür ausreicht, mehr Klammern zu tippen, als du mit dem neuen Dialekt in deinem ganzen Leben sparen wirst :-)
Besserwessi
29.10.2010, 20:35
Es ist zwar eine absolute Unart, aber wenn man unbedingt will, kann man sich Makros definieren, so dass man statt den Klammern {} auch BEGIN END schreiben kann. Sieht dann etwas nach MODULA aus, aber immer noch mit allen Nachteilen von C.
Wenn dann die Taste fürs E abgenutzt ist kann man immer noch {} schreiben.
Hmm, C hat zu viele Klammern?
Dann probier doch mal Lisp ;-)
SprinterSB
29.10.2010, 22:00
Hmm, C hat zu viele Klammern?
Dann probier doch mal Lisp ;-)
hehe, der ist gut!
.. zum Beispiel:
if testflag
{
}
oder if (x==1)
Was sollen denn da die Klammern. Das ändert weder mathematisch was, noch gäbe es irgendwelche anderen Interpretationen für den Compiler ...
Doch gibt es. Beispiel
if (a)
+b;
Wenn man jetzt die Klammern um a weg lässt, ist es alles andere als eindeutig, ob nun a die Bedingung und +b; das auszuführende Statement ist oder ob a +b die Bedingung ist und ; das Statement. Klar kommt sowas ziemlich selten vor, ist aber immer noch syntaktisch völlig korrekter Code.
MfG Mark
radbruch
30.10.2010, 14:09
So ist eben die C-Syntax. Wo ist das Problem?
#define testflag (x==1)
if testflag
while testflag
x=0;
Jeder kann sich sein eigenes C schaffen ;)
http://www.parallelnetz.de/CHater.html
(Hab' ich das hier aufgesammelt?)
Gruß
mic
... Deine Codesample wird bestimmt in einem ISR aufregufen und X ist volatile ?
... man man man ich klink mich aus.
Hinter der C-Syntax steckt Absicht, wie man inzwischen weiss:
...und entwickelten daraufhin B, BCPL und schließlich C. Wir hörten auf, als es uns gelang, den Ausdruck
C/C++ Code:
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8 )%2))P("| "+(*u/4)%2);
fehlerfrei zu compilieren.
Zu denken, daß moderne Programmierer versuchen würden, eine Sprache zu benutzen, die derartige Ausdrücke zuläßt, lag weit außerhalb unseres Verständnisses. Wir dachten daran, das ganze an die Sowjets zu verkaufen, um den Fortschritt ihrer Computerwissenschaft um 20 Jahre zurück zu werfen
... Deine Codesample wird bestimmt in einem ISR aufregufen und X ist volatile ?
... man man man ich klink mich aus.
Warum?! Schau dir an was #define macht und fertig.
Erstmal versuchen es zu verstehen, dann jammern...
radbruch
30.10.2010, 18:29
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8 )%2))P("| "+(*u/4)%2);
http://www.google.de/search?q=for%28%3BP%28%22\n%22%29%2CR--%3BP%28%22|%22%29%29for%28e%3DC%3Be--%3BP%28%22_%22%2B%28*u%2B%2B%2F8+%29%252%29%29P%28 %22|+%22%2B%28*u%2F4%29%252%29%3B
324 Millionen Fundstellen!?!
*lol*
Und was gibt es an der Code Zeile worüber man sich aufregen sollte?
Da ist ja das Schlimme: Kein C-Programmierer findet diese Zeile irgendwie aussergewöhnlich
Kann man daraus Rückschlusse auf die Denkweise ziehen ?
radbruch
30.10.2010, 19:14
Da ist nichts, worüber man sich aufregen sollte. Die Codezeile ist lediglich ein Beispiel dafür, was man in C formulieren können sollte. Dass C das Allheilmittel (http://de.wikipedia.org/wiki/Panazee) ist glaube ich auch nicht.
Schade nur, daß die Klammern auf den deutschen Tastaturen nicht direkt nebeneinander lliegen und man nur per ALT GR drankommt.
Ich hätte ja gedacht, daß man beim definieren des Tastenlayouts die C Programmierer berücksichtigt und diese Tasten extra gut erreichbar macht.
Aber das war wohl kein Kriterium.
Vielleicht sollte man sich als C-Anfänger einfach eine amerikanische Tastatur zulegen, dann verknotet man sich nur das Gehirn, und nicht auch noch die Finger :)
Gruß
Christopher
oberallgeier
30.10.2010, 19:59
... C hat zu viele Klammern ... probier doch mal LispAlso Lisp fand ich eigenlich - na ja, anfangs richtig grausam. Hinterher - gefiel es mir sogar. Ich hatte mir vor Jahren einen Offset zu einem computer aided anything Programm geschrieben. In Lisp. Und insgesamt waren das zig Seiten - aber unter 200.
... Vielleicht sollte man sich ... eine amerikanische Tastatur zulegen ...Beim Lisp-eln hatte ich zeitweise die Tastatur geändert und eine QWERTY initialisiert. Da ich genug Übung mit dieser Tastenbelegung hatte und ausserdem damit - und mit der deutschen Belegung - blind schreiben konnte, war das kein Problem. Auf die Dauer natürlich schon lästig. Aber ein interessantens Experiment für mich. Der Vorschlag von chr-mt ist also sinnvoll - allerdings wird ein flüssiger Schreiber beim be-tasten der amerikanischen Tastatur schon Umstellungsschwierigkeiten haben, auch wenn eine korrekt beschriebene da liegt. Ein Ungeübter wird einfach . . . . . total ausgebremst werden und schließlich in beiden Layouts ins Schleudern kommen.
Besserwessi
30.10.2010, 20:21
Die Sprache C wurde halt mit einer amerikanischen Tastatur entwickelt. Die Deutsche Tastatur-belegung ist aber auch schon älter als C.
So schlimm ist das mit Tasten aber auch nicht: Wenn man die Mengenklammern gleich paarweise eingibt, braucht man nur 1 mal Alt -Gr drücken, und auch an die Tastenkombination gewöhnt man sich.
Das Arbeiten mit 2 Tastaturbelegungen ist wirklich gewöhnungsbedürftig (schon Probiert mit PCs, das Notebook mit US-Tasten). Zum Blind tippen nicht so geeignet, vor allem bei den Sonderzeichen die man nicht ständig braucht.
C ist auch eher eine Sprache wo das reine Tippen relativ schnell geht, aber dafür das suchen nach Fehlern etwas länger dauert. Also daher eigentlich weniger für längere Programme geeignet.
In dem Zusammenhang schmeiss ich mal diesen Link in den Raum, zwar schon sehr alt, kennt aber sicher nicht jeder: http://99-bottles-of-beer.net/
Da gibts n paar Sprachen die noch deutlich "schlimmer" sind als die bekannte Zeile in C... auch wenn ein paar Sprachen nciht wirklich ernst gemeint sind.
> C .. Also daher eigentlich weniger für längere Programme geeignet.
da irrst Du Dich gewaltig - C ist ein Handwerkszeug (so wie jede Programmiersprache)
C ermöglicht eben nur so wenig wir möglich tippen zu müssen, Betonung liegt auf müssen, C steht und fällt mir dessen sinnvoller Anwendung und der Disziplin und dem Können des Programmierers.
Ohne Hirn ist C wertlos, mit Hirn ist es die Basis für viel, was uns "umgibt".
C ist ein Macroassembler, andere sagen, ein Aprilscherz, ...
Besserwessi
30.10.2010, 23:59
Je länger ein Programm ist, desto größer wird der Anteil der Zeit den man mit dem Debuggen verbringt. Da ist dann die Qualität des Debuggers ein wichtiges Kriterium. Die Zeit zum eintippen kann man da schon fast vernachlässigen.
Nicht umsonst gibt es die Weiterentwicklungen C++, C# und andere Sprachen wie ADA oder Java. Ein Motivation ist dabei sicher auch die Fehler leichter finden zu können, bzw gar nicht erst so viele zu machen. Viele der dummen Fehler die man in C machen kann, kann da schon der Compiler finden.
Die weiterentwickelten Sprachen erzwingen (zumindest teilweise) die Disziplin, die man in C einhalten sollte damit das Programm verständlich bleibt. Hier ist dann der Druck des Compilers einfach besser als die beste Selbstdisziplin.
Ich weiß dass auch viele größere Programme in C geschrieben wurden und wohl auch noch teilweise werden. Das heißt aber nicht das C hier ein gute Wahl ist, zumindest wenn man auf halbwegs wenig Fehler Wert legt.
Ich bin ja wirklich erstaunt, daß mein Frage ein recht reges Interesse geweckt hat.
Naja, ich werd wohl niemals die Zeit für die beiden Klammern benötigen, die aufgrund meiner Frage
hier deswegen verbraten wurde :-)
Was hab ich für ein Problem mit "C" ?????
Angefangen hat alles mit Bits und Bytes.
"C" kennt aber gar kein Byte.
Das kann man sich dann selbst definieren, (unsigned char)
also eine Ableitung von einem "negativen Ascii-Character" ohne Vorzeichen.
Was für ein Scheiss ist das denn....
Bei Abfragen ob etwas gleich ist, muss man
nicht etwa "=" schreiben, das wär wohl zu "ungenau",
nein, man muss "==" schreiben, also "besonders gleich"
Vernünftige Compiler können Boolsche Ausdrücke von logischen Ausdrücken
selbst unterscheiden. Bei "C" geht das nicht. Und da es schon nicht geht,
können wir auch gleich noch entsprechende Sonderzeichen einführen,
dann merkt man das nicht sofort.
Aus XOR wird ^
aus AND wird &
Und auch hier heisst es wieder "besonders und" && oder
besonders oder "||" was generell mit Klammern umschrieben wird.
Naja wen wundert es da noch, daß man für "<>" kleiner größer auch gleich
was neues erfunden hat: != also "Achtung Nicht Gleich" ist gemeint.
Achja, habt Ihr schon mal versucht mit Strings zu arbeiten in "C"
Das war anscheinend nie vorgesehen und so hat man eine Bibliothek
namens "strings" rangebastelt.
Nun sollte man aber nicht glauben, daß man damit "vernünftig" arbeiten kann.
Wo ist denn die Funktion zum Einfügen eines Characters oder Strings in einen
Vorhandenen ??? "StrIns" oder so ähnlich....
Da ich schon beim Thema Strings bin, kann ich folgendes definieren in C
char name[]="Hallo";
wenn ich das im Programmcode versuche:
name = "Hallo"; geht es plötzlich nicht mehr.
Nun muss ich mit "strcpy" arbeiten. Also von Hinten Durch Die Brust Ins Auge....
Die Fehlerhäufigkeit in meiner Software ist exponentiell zum "verkürzten, kryptischen C Code"
angestiegen. Und Gott und die Welt programmiert nun mit dem Schei........
und leider hat mich meine Firma auch dazu verbannt.
Was solls, im nächsten Leben werd ich Gärtner........
Ich wünsche allen ein "absturzfreies" Wochenende.
Siro
So nun möche ich aber etwas positive ssagen:
Den letzten Artikel von "Besserwessi" finde ich sehr gut.
Die neueren Compiler zwingen einem schon eine gewisse Disziplin einzuhalten.
Das find ich auch gut so, lieber einen Warning mehr, der im Vorfeld schon auf Fehler
deuten kann. Auch meine negative Äußerung , was z.B die Stringverarbeitung angeht,
ist ja schon wesentlich besser gelöst worden in C++ Jave usw.
Hatte übrigens Pascal schon von Anfang an besser gelöst.
Nullterminierte Strings sind einfach "Grütze" darf ich das so sagen ???
Erstmal "durchhechten" wo denn die 0 zu finden ist. Wenns dann etliche Kilobyte sind
absolute Resourcenverschwendung.
Aber ein Thema habe ich bisher noch garnicht angesprochen:
Das betrifft vermutlich alle Hochsprachen. Für eine komplexe Software oder auch nur
zur Dokumentation hat man (hoffentlich) ein Flussdiagramm, Ablaufdiagramm Jordan oder
was auch immer. Durch die Optimierung eines Compilers, stimmt dieser Ablauf aber
unter Umständen garnicht mehr. Wenn ich im Diagramm festlege, daß bei
einem bestimmten Ereignis z.B eine Unterfunktion angesprungen wird und es auch so
programmiert habe, kann mir der Compiler einen Strich durch die Rechnung machen.
Je nach Einstellung macht er plötzlich keinen Unterprogrammaufruf sondern fügt den Code direkt
in das aufrufende Programm ein. Das spart Zeit, ist schlau und auch funktionell. Leider entspricht
es nicht meinem Flussdiagramm. Wenn ich z.B eine Stackbelastung vorausberechne liege ich dann
falsch, diesmal im positiven Sinne, weil weniger Stack benötigt wird. Es könnte aber auch sein,
daß ich mich darauf verlassen habe, daß mittels Assembler Code auf die Stackvariablen zugegriffen
wird. Das weis natürlich nicht der Compiler und es würde in die Hose gehen. Hier habe ich aber
schon aus diesem Forum erfahren, daß die meisten Compiler eine Schalter haben um diese Optimierung
abzuschalten. -noinline oder ähnliches.
Na wie dem auch sei. Einen wirklich "Eindeutigen" Code, unabhängig von irgend welchen Compiler
Einstellugnen, habe ich nur wenn ich in Assembler programmiere. Das hab ich auch die letzten 30
Jahre getan. Nun blick ich oftmals durch den erzeugten Code vom C-Compiler nicht mehr durch.
Ist schon "witzig" je nach Compiler Einstellung ist mein Code zur Zeit 14 KByte oder 8 KByte
groß. Wie soll man denn das dokumentieren ? zwecks ISO usw. ????
Was steht denn in den "verlorenen" 6 KByte ??? Für Sicherheitsrelevenate Anwendungen z.B.
in der Medizintechnik ist das für mich unverantwortlich, mal eben 6 KByte Code wegzulassen.
Wenns dann funktioniert okay....
In Assembler konnte ich bisher jedes Bit nachweisen, was es tut, warum, und zu welchem Zeitpunkt.
In C kann ich ja nichtmal die Laufzeit angeben für eine Funktion, da sie sich je nach Optimierung
ändert. InAssembler habe ich die Laufzeiten in Nano Sekunden dokumentieren können.
Bin ich ein "C"-Gegner ? Jaaaaaaaaa
Siro
Angefangen hat alles mit Bits und Bytes.
"C" kennt aber gar kein Byte.
Das kann man sich dann selbst definieren, (unsigned char)
also eine Ableitung von einem "negativen Ascii-Character" ohne Vorzeichen.
Was für ein Scheiss ist das denn....
Und wo ist da nun das Problem? 8 Bit sind 8 Bit, egal wie du es nennst.
Bei Abfragen ob etwas gleich ist, muss man
nicht etwa "=" schreiben, das wär wohl zu "ungenau",
nein, man muss "==" schreiben, also "besonders gleich"
if(a=b) und if(a==b sind nunmal 2 völlig unterschiedliche Dinge!
Vernünftige Compiler können Boolsche Ausdrücke von logischen Ausdrücken
selbst unterscheiden. Bei "C" geht das nicht. Und da es schon nicht geht,
können wir auch gleich noch entsprechende Sonderzeichen einführen,
dann merkt man das nicht sofort.
Aus XOR wird ^
aus AND wird &
Und auch hier heisst es wieder "besonders und" && oder
besonders oder "||" was generell mit Klammern umschrieben wird.
Naja wen wundert es da noch, daß man für "<>" kleiner größer auch gleich
was neues erfunden hat: != also "Achtung Nicht Gleich" ist gemeint.
Achja, habt Ihr schon mal versucht mit Strings zu arbeiten in "C"
Das war anscheinend nie vorgesehen und so hat man eine Bibliothek
namens "strings" rangebastelt.
Und welche Sprache macht das anders?!
Nun sollte man aber nicht glauben, daß man damit "vernünftig" arbeiten kann.
Wo ist denn die Funktion zum Einfügen eines Characters oder Strings in einen
Vorhandenen ??? "StrIns" oder so ähnlich....
Es gibt in C einige Funktionen zum Arbeiten mit Zeichenketten, bzw. char-Arrays!
Da ich schon beim Thema Strings bin, kann ich folgendes definieren in C
char name[]="Hallo";
wenn ich das im Programmcode versuche:
name = "Hallo"; geht es plötzlich nicht mehr.
Richtig, aber auch dafür gibt es Funktionen, mit denen das schnell und einfach geht!
Die Fehlerhäufigkeit in meiner Software ist exponentiell zum "verkürzten, kryptischen C Code"
angestiegen. Und Gott und die Welt programmiert nun mit dem Schei........
Nur weil dir der Compiler bzw. die Entwicklungsumgebung die Arbeit nicht abnimmt...
Den letzten Artikel von "Besserwessi" finde ich sehr gut.
Die neueren Compiler zwingen einem schon eine gewisse Disziplin einzuhalten.
Das find ich auch gut so, lieber einen Warning mehr, der im Vorfeld schon auf Fehler
deuten kann. Auch meine negative Äußerung , was z.B die Stringverarbeitung angeht,
ist ja schon wesentlich besser gelöst worden in C++ Jave usw.
Hatte übrigens Pascal schon von Anfang an besser gelöst.
Nullterminierte Strings sind einfach "Grütze" darf ich das so sagen ???Haben in anderen Sprachen Strings kein Ende?! Auch da nimmt dir der Compiler nur etwas arbeit ab. Dafür hast du wiederrum in C viel mehr Möglichkeiten, was natürlich schlecht ist wenn man nciht weiss was man tut.
Hier habe ich aber
schon aus diesem Forum erfahren, daß die meisten Compiler eine Schalter haben um diese Optimierung
abzuschalten. -noinline oder ähnliches.
Oder auch in mehreren Stufen, mehr oder weniger Sinnvoll...
Was steht denn in den "verlorenen" 6 KByte ??? Für Sicherheitsrelevenate Anwendungen z.B.
in der Medizintechnik ist das für mich unverantwortlich, mal eben 6 KByte Code wegzulassen.
Wenns dann funktioniert okay....
Der Code ist ja nun nicht einfach weg! Der wurde optimiert, und Teile wenn sie garnicht verwendet werden weggelassen. Gerade bei der µC Programmierung auf Grund des geringen Speicherplatzes oft sehr hilfsreich.
Bin ich ein "C"-Gegner ? Jaaaaaaaaa
Ja wenn du schon 30 Jahre in Assembler programmierst, dann is auch klar warum... Mir kommt es eher so als würdest du es garnicht verstehen wollen. Man könnte dir wahrscheinlich 100 Argumente für C geben und trotzdem würdest du es nicht akzeptieren wollen.
Hi,
ich kann Siro da durchaus verstehen.
Ich sehe das Problem einfach darin, daß man bei C ein Programm nicht mal eben "mit dem gesunden Menschenverstand" verstehen bzw. in den normalen Sprachgebrauch übersetzen kann.
Während man zB. den Quellcode eines Basic Programmes oft durch die wörtliche Übersetzung der Befehle ins Deutsche irgendwie sinngemäß verstehen kann, ist das bei C etwas anders.
Do Loop ist übersetzt "tue Schleife" und darunter kann man sich grob was vorstellen.
Übersetzt man dagegen while(1) , also "während 1" ist das ja irgendwie etwas weniger offensichtlich.
if(a=b) und if(a==b sind nunmal 2 völlig unterschiedliche Dinge!
Und da ist wieder das Problem mit der einfachen Verständlichkeit.
Aus XOR wird ^
Der Eindruck, den ich von C bisher habe, ist, daß man hier einige Dinge mit Gewalt unverständlich ausdrücken wollte, warum auch immer. :)
Nun ja, ist alles Gewohnheitssache.
Gruß
Christopher
SprinterSB
05.11.2010, 23:53
Was hab ich für ein Problem mit "C" ?????
Angefangen hat alles mit Bits und Bytes.
"C" kennt aber gar kein Byte.
Das kann man sich dann selbst definieren, (unsigned char)
Besser ist, ein Standard-Header wie <stdint.h> zu verwenden und Typen wie uint8_t, ein unsigned int, der 8 Bit breit ist. Ja, du kannst fluchen wie'n pubertierender Rohrspatz, aber wenn du durch musst, musst du eben durch. Rumzetern bringt dir nix ausser Magengeschwüre. Oder nen neuen Job suchen. Oder die Putze macht den C-Kram und du die Klo-Kosmethik...
Anfangs kannst du es noch auf das Sche..-C schieben, wenn dir alles um die Ohren fliegt, aber irgendwann bleibt's an dir hängen wenn du es nicht lernen willst.
also eine Ableitung von einem "negativen Ascii-Character" ohne Vorzeichen.
Was für ein Scheiss ist das denn....
nö, unsigned heisst, daß das höchstwertige Bit nicht als Vorzeichen interpretiert wird, im Gegensatz zum signed.
Bei Abfragen ob etwas gleich ist, muss man
nicht etwa "=" schreiben, das wär wohl zu "ungenau",
nein, man muss "==" schreiben, also "besonders gleich"
Vernünftige Compiler können Boolsche Ausdrücke von logischen Ausdrücken selbst unterscheiden. Bei "C" geht das nicht. Und da es schon nicht geht, können wir auch gleich noch entsprechende Sonderzeichen einführen, dann merkt man das nicht sofort.
Dir ist klar, daß C 40 Jahre alt ist? Es würde nicht entworfen, um leicht verständlich zu sein. Es wurde nicht von Bastlern entworfen und war auch nicht für Bastler gedacht. Zu der Zeit war man froh, daß es überhaupt möglich war, Compiler zu schreiben und die Assembler-Untiefen zu verlassen. Heutige Sprachen können viel mehr, aber nen Garbage-Collector oder Hashtables wie in Java, die zur Sprache dazu gehören, waren damals einfach unvorstellbar. C läuft vielfach "on the bare metal", auch heute noch. Der Erfolg der Sprache ist auch darin begründet, daß eben nicht ständig daran rumgesäbelt würde uns es abertausende Dialekte gibt die die Portierbarkeit komplett untergraben.
Aus XOR wird ^
aus AND wird &
Und auch hier heisst es wieder "besonders und" && oder
besonders oder "||" was generell mit Klammern umschrieben wird.
Naja wen wundert es da noch, daß man für "<>" kleiner größer auch gleich
was neues erfunden hat: != also "Achtung Nicht Gleich" ist gemeint.
Achja, habt Ihr schon mal versucht mit Strings zu arbeiten in "C"
Das war anscheinend nie vorgesehen und so hat man eine Bibliothek
namens "strings" rangebastelt.
Wozu soll das in den Sprachkern, wenn's in einer Bibliothek geht? Ist in C++ auch so, es ist in Java so (nicht unbedingt mit Strings aber viele andere Sachen sind in Libs), es ist in Python so und weiß der Teufel wo noch überall.
Nun sollte man aber nicht glauben, daß man damit "vernünftig" arbeiten kann.
Doch. Wenn man weiß was man tut, durchaus. Einfach mal rumtippsen nach dem Motto "ja, wird schon gehen ich tippse einfach mal was zusammen" wie in Clicki-Bunti funktioniert eben nicht und früher oder später hat's dich am Arcsh.
Wo ist denn die Funktion zum Einfügen eines Characters oder Strings in einen
Vorhandenen ???
Nimm eine Bibliothek. Oder schreib dir eine. Du hast eine Turing-vollständige Sprache zur Hand, mit der geht das :o)
Die Fehlerhäufigkeit in meiner Software ist exponentiell zum "verkürzten, kryptischen C Code" angestiegen.
Die Fehlerhäufigkeit steigt exponentiell mit der Unkenntnis der Sprache.
Nullterminierte Strings sind einfach "Grütze" darf ich das so sagen ???
Erstmal "durchhechten" wo denn die 0 zu finden ist. Wenns dann etliche Kilobyte sind absolute Resourcenverschwendung.
Wenn du es effizient haben willst, schiele nicht auf Java (da ist es nämlich eben /nicht/ effizient, sondern suche nach effizienten Lösungen in C. Wenn es günstig ist, die Länge mitzuführen, dann bau dir Funktionen/Datentypen, die das für dich erledigen und verwende sie.
Für eine komplexe Software oder auch nur zur Dokumentation hat man (hoffentlich) ein Flussdiagramm, Ablaufdiagramm Jordan oder was auch immer. Durch die Optimierung eines Compilers, stimmt dieser Ablauf aber unter Umständen garnicht mehr.
Falsch. Wenn der Ablauf nicht stimmt, hat der Compiler einen Fehler. Eine Sprache wie C hat eine bestimmte Semantik, die festlegt, was was bedeutet und wie was umgesetzt wird. In C ist es das Konzept einer abstrakten Maschine, deren Zustand an bestimmten Stellen mit denen der realen Maschine übereinstimmen. Diese Stellen heissen "sequence points". Die reale Maschine wiederum wird durch Code dargestellt , der sich so zu verhalten hat, wie dir abstrakte Maschine.
Wenn ich im Diagramm festlege, daß bei einem bestimmten Ereignis z.B eine Unterfunktion angesprungen wird und es auch so
programmiert habe, kann mir der Compiler einen Strich durch die Rechnung machen. Je nach Einstellung macht er plötzlich keinen Unterprogrammaufruf sondern fügt den Code direkt in das aufrufende Programm ein. Das spart Zeit, ist schlau und auch funktionell. Leider entspricht es nicht meinem Flussdiagramm.
Siehe oben. Man kann auch erzwingen, daß ein Funktionsaufrur getätigt wird, aber wenn du davon ausgehst, daß er auf jenen Fall stattfindet oder auf keinen Fall stattfindet wenn da inline steht, hat deine Anwendung ein Problem. Gleiches gilt für Schleifen, das Anlegen von Variablen, für Speicherzugriffe, oder was auch immer: Das Programm muss sich nur nach dem verhalten, was in der Quelle steht, es aber nicht wirklich tun. Steht da a=1; a=a+2 kann der Compiler ein a=3 daraus machen oder es ganz weglassen wenn a nie verwendet wird.
Wenn ich z.B eine Stackbelastung vorausberechne liege ich dann
falsch, diesmal im positiven Sinne, weil weniger Stack benötigt wird. Es könnte aber auch sein, daß ich mich darauf verlassen habe, daß mittels Assembler Code auf die Stackvariablen zugegriffen wird. Das weis natürlich nicht der Compiler und es würde in die Hose gehen. Hier habe ich aber schon aus diesem Forum erfahren, daß die meisten Compiler eine Schalter haben um diese Optimierung abzuschalten. -noinline oder ähnliches.
Optimierung ganz zu deaktivieren ist eine Option. Das entbindet dich aber nicht davon, die Sprache zu beherrschen. Dann: wo ist da Assembler? Wenn du in Assembler schreibst, musst du spezielle Regeln einhalten und dich nach dem ABI des Compilers richten. Das wird nochmal unbequemer. Du kannst nicht einfach non chalant Assembler und C (oder irgend eine andere Hochsprache) mischen und erwarten das das funktioniert.
Einen wirklich "Eindeutigen" Code, unabhängig von irgend welchen Compiler Einstellugnen, habe ich nur wenn ich in Assembler programmiere.
Nein, je nach Assembler noch nicht mal das. Es gibt Assembler, die zB Branch-Relaxing ausführen oder Hardware-Bugs umschiffen.
Das hab ich auch die letzten 30 Jahre getan. Nun blick ich oftmals durch den erzeugten Code vom C-Compiler nicht mehr durch.
Das ist auch ganz und garnicht einfach, selbst mit einem guten Debugger. Aber mit Asm-Erfahrung hast du da gute Voraussetzungen. Wenn dir was in C nuklar ist, kannst du zB ne kleine Testfunktion machen und siehst, wie der Compiler das umsetzt und kommst so vielleicht besser in die Sprache ran als mit Büchern.
Ist schon "witzig" je nach Compiler Einstellung ist mein Code zur Zeit 14 KByte oder 8 KByte groß. Wie soll man denn das dokumentieren ? zwecks ISO usw. ???? Was steht denn in den "verlorenen" 6 KByte ??? Für Sicherheitsrelevenate Anwendungen z.B. in der Medizintechnik ist das für mich unverantwortlich, mal eben 6 KByte Code wegzulassen. Wenns dann funktioniert okay....
In Assembler konnte ich bisher jedes Bit nachweisen, was es tut, warum, und zu welchem Zeitpunkt.
Die 8kB waren dann schlichtweg nicht notwendig. Der Compiler hat das erkannt und Code wiederverwendet, nicht verwendete Sachen rausgeschmissen, was auch immer.
Der Nachweis muss muss dann eben jetzt auf C-Ebene geschehen oder mit Hardware-Unterstützung (Timer, ...) Inline-Assembler ist eine Option, aber es ist in den meisten Fällen weder notwendig noch dient es der Verständlichkeit, Wartbarkeit oder Portierbarkeit. Falls Für irgendwas Ticks gezählt werden müssen, kommt man an Assenbler nicht vorbei.
In C kann ich ja nichtmal die Laufzeit angeben für eine Funktion, da sie sich je nach Optimierung ändert. In Assembler habe ich die Laufzeiten in Nano Sekunden dokumentieren können.
Auf einer Hardware, die mehrere Pilelines hat, unterschiedlich schnelle Speicher anbindet, über Caches verfügt, Delay-Slots hat, Jump Prediction, oder mit Hardware-Bugs gepflastert, wirst du dir da die Finger blutig rechnen und einem C-Compiler die Füsse küssen.
Was sicherheitskritische Anwendungen angeht: Hier mit Bleistift und Papier einem Compiler hinterher zu rechnen (selbst wenn er nicht optimiert), ist keinem Progrmmierer zuzumuten. Wenn deinem Arbeitgeben das Kleingelt für entsprechende Tools fehlt, soll er dich weiter in Assembler schreiben lassen. Für Sicherheitsfritische Saftware im Bereich AKW oder Avionics sind entsprechende Tools schon für läppische 40000€ zu haben (benötigte Hardware und Analysezeit nicht eingerechnet), für Medizintechnik wird also die Portokasse deines Brötchengebers reichen.
Von Hand nachrechnen ist auch daher inakzeptabel, weil Codeänderungen /nicht/ lokal sind, d.h. eine Änderung im Code kann sich an ganz andere Stelle so auswirken, daß der Compiler zB anderer Register als günstig erachtet (so wie du es als Asm-Progger auch machen könntest, aber um Änderungen lokal zu halten eben nicht tust) und die komplette Rechnung neu angefangen werden muss. Oder es wird komplett ohne Optimierung gearbeitet (was je nach Sicherheitsstufe angezeigt ist) aber dann muss die Hardware deutlich fetter ausgelegt werden, da ein C-Compiler dann wesentlich mehr Overhead erzeugt als ein Assembler-Programmierer (sowohl was Laufzeit als auch was Codedichte uns Stackbedarf angeht).
Bei Java wären solche Zeitabschätzungen gar nicht mehr möglich.
Wer zwingt dich, dich mit C zu beschäftigen, obwohl du es für bescheuert hältst ?
Lass es doch einfach
Do Loop ist übersetzt "tue Schleife" und darunter kann man sich grob was vorstellen.
Übersetzt man dagegen while(1) , also "während 1" ist das ja irgendwie etwas weniger offensichtlich.
Dann übersetz es mal richtig! Es heisst nicht "während 1" sondern "solange(der ausdruck in den klammern wahr ist) und da 1 immer wahr ist...
Zitat:
if(a=b) und if(a==b sind nunmal 2 völlig unterschiedliche Dinge!
Und da ist wieder das Problem mit der einfachen Verständlichkeit.
Dann versuch es doch mal zu verstehen!
Der Eindruck, den ich von C bisher habe, ist, daß man hier einige Dinge mit Gewalt unverständlich ausdrücken wollte, warum auch immer.
Ja klar, genau deshalb wurde es erfunden! Eines der unsinnigsten Kommentare in diesem Thread...
zu chr-mt:
ich glaube auch manchmal, daß es garnicht gewollt ist den Code zu verstehen.
Das muss umständlich sein, sonst könnte es ja jeder.....
Wenn Du heute jemanden erzählst Du programmierst in Basic oder Pascal dann rümpfen sie wohl eher die Nase. Da ist der Syntax recht eindeutig, daß sogar Laien den Ablauf schnell verstehen.
Wie dem auch sei, ich will C nicht nur schlecht machen, bin aber wirklich erstaunt, daß sich diese Sprache so durchsetzten konnte. Ich hätte (habe) solange wie es möglich war Pascal, Delphi vorgezogen und natürlich Assembler. Für größere Projekte ist Assembler dann wirklich nicht mehr geeignet und eine Hochsprache muss ran. Die heutigen Compiler erzeugen durchweg alle recht kompakten Code unabhängig von der
verwendeten Hochsprache.
Übrigens meine erste Hochsprache war PL/M80
Ich würd mal sagen fast wie Pascal. Fand und finde ich heut noch super.
Und dann Turbo-Pascal, das war doch der absolute Hammer. Der Compiler passte übrigens auf eine Diskette und ein Compilat war auf einem 8Mhz Rechner eigentlich schon fertig wenn man auf die Taste drückte. Aber ich befinde mich ja im C Forum, also werde ich das "schwärmen" mal lassen....
und bitte nicht alles zu negtiv auffassen, wenn man sich mal Luft machen muss.......
Weiter gehts in C, ich werd mich da schon reinfummeln, wär doch gelacht :-)
ich hab Euch mal ein kleines Auszug (Infoblatt) von meiner C-Programmierung angehangen, nicht daß es heist ich beschäftige mich damit nicht. Das hab ich mir selbst erarbeitet und muss immer wieder mal reinschauen wie das geht. Vielleicht ist das für den einen oder anderen auch mal interessant. Wenn da Fehler drin sind, bitte meckern.
Siro
Sieh es doch mal anders, wer C versteht, versteh auch alle anderen Sprachen recht schnell. So geht/ging es mir jedenfalls.
oberallgeier
06.11.2010, 10:24
... und bitte nicht alles zu negtiv auffassen, wenn man sich mal Luft machen muss ...Ist schon klar, so etwas überkommt einen manchmal - nicht nur bei C (das bei mir immer wieder Cäh heißt).
... ich glaube auch manchmal, daß es garnicht gewollt ist den Code zu verstehen ...Stimmt - genauso wie man Formeil1-Autos nur baut, dass fast alle Menschen sich damit umgehend erschlagen - WENN sie sich mal reinsetzten dürften - und die hochrangigen Könner schrotten die auch regelmässig. Einfach unfahrbare Dinge, gebaut von Noncompos und grobmotorischen Schraubern. Und ich kenne auch Kletterrouten, die sind nur so ausgeschraubt, dass möglichst keiner da rauf kommt. Denn andere Routen zeigen, dass es auch viel einfacher geht. Und warum sollte man Schach spielen, wo doch MauMau viel einfacher ist.
... C ... bin ... erstaunt, daß sich diese Sprache so durchsetzten konnte ...Neee, bist Du nicht. Weil Du vermutlich schon etwas über die MÖGLICHKEIT der Hardwarenähe von C gehört hast und über deren Portierbarkeit und und und. Und Assembler - jeder Hardwarebauer hat sich für die Befehle andere Abkürzungen ausgedacht, andere Registernamen, Sprungmöglichkeiten und so. Bei denen wird doch Variation ziemlich groß geschrieben. Richtig bescheuerte Sprachen oder Implementationen - mir fällt gerade UCSD_Pascal ein, sind schon längst ausgestorben. Seltsam, dass C überlebt hat.
... meine erste Hochsprache war PL ...Dann programmier doch mal einen Mikrocontroller-Port mit PL.
... und ein Compilat war auf einem 8Mhz Rechner eigentlich schon fertig wenn man auf die Taste drückte ...Du Glücklicher. Zu Zeiten, als man 8086 beim Hersteller in Westentaschenmengen persönlich abholte, hatte ich 8086er programmiert, u.a. mit FORTRAN. Da wurde vormittags geschrieben und nach dem Compilerstart ging man in die Kantine. Ok, ok, die liefen auch selten über 4 MHz.
... Weiter gehts in C, ich werd mich da schon reinfummeln, wär doch gelacht ...Hast ja genug Dampf abgelassen, hast einige auf die Palme gebracht - also dann mach zu. Und übrigens: ich wünsche Dir von ganzem Herzen viel Erfolg.
Siro, wenn Du so verbal rumfurzt, darf man das auch in Deine Richtung ?
Schon Deine Eingangsfrage nach dem Sinn von Klammern werte ich als ein Zeichen Deiner Intoleranz, weniger Deinem möglichen wahrhaftige Unverständnis.
Ich wundere mich nur, daß Du mit 30 Jahren asm-Erfahrung so einen unverständlichen Müll schreibst. Gerade dann solltest Du C verstehen.
Sicher ist nicht alles optimal gelöst, aber dafür prägnant.
Ein int8_t kann man nunmal als 7 Bit plus Vorzeichen oder eben als 8 Bit interpretieren.
Ein String hat immer ein Endekennzeichen, auch wenn C++ und andere eine Klasse oder modulares overhead drumrum bauen.
Deine Kritik am "=" "||" & Co. zeigen Deine Engstirnigkeit in Bezug auf eine Syntax auf. Du bist wie ein fauler 8-Klässler, statt zu lernen, pubertäres Meckern.
Und wenn Du Dich jetzt aufregst, wieso greift der Depp mich so ausfallend an, dann frag Dich mal, was Du hier gegenüber der ehrenwerten Sprache C tust!
Wenn es Dir auf genaue Laufzeitbestimmung im nanosekunden-Bereich ankommt, dann ist asm das beste Mittel der Wahl. Ich kann mir kaum vorstellen, daß C++, Java oder gar Modula diesbezüglich irgendwie abschätzbar sind.
Also werkel doch einfach weiter in Basic und Klappe halten !
*freundliches Lächeln* !
BurningWave
06.11.2010, 13:22
@Siro
Wenn dir mal langweilig ist hätte ich ne Idee, was du machen könntest: Du könntest mal ein einfaches Programm für Windows (wie einen Texteditor) in Assembler schreiben ohne auf irgendwelche weiteren C/C++ Bibliotheken zurück zu greifen. Viel Spass!
Man merkt wirklich wie wenig Ahnung du von C hast. Sonst würdest du nicht so dumm-dreiste Behauptungen aufstellen. Klammern und Operatoren wie ^ & | usw. tragen nur der Übersichtlichkeit bei und haben eine gewisse Nähe zu Assembler. Warum ärgerst du dich überhaupt über ein paar evtl. unnötige Klammern, wenn du dafür "AND" statt & benutzen willst?
Du hast wohl auch nicht bedacht, dass man das Ende von nullterminierten Strings viel einfacher erkennen kann und dass (fast) alles in C/C++ einen tieferen Sinn hat, den man aber nur versteht, wenn man sich wirklich auskennt, bzw. Erfahrung hat. Wie gesagt es ist technisch unmöglich mit Assembler Programme für Windows zu schreiben, die nicht nur in der Kommandozeile laufen.
Du solltest einfach einsehen, dass Technik Fortschritte macht und alte Sachen teilweise überholt werden. Du kannst ja noch eine Weile warten, dann gibt es irgendwann C++0x, das einige deiner Mängel beheben wird.
okay, ich bin wohl ein Idiot, werde mich wohl aus diesem Forum ausklinken.
entschuldigt, wenn ich euch auf den Schlips getreten bin....
Siro
Das ist echt arm!!!
Erst solche haltlosen Behauptungen raushaun und dann den Schwanz einziehen...
Viel Glück im nächsten Forum...
Weist Du R2D2, da ich grad eine "Zensierung" erhalten habe, obwohl ich mich selbst als "Idiot" bezeichnet habe, brauche ich auf deine "dumm-freiste Behauptung" die Du mir grad vorgeworfen hast auch nicht weiter eingehen. Ich hatte nur eine simple Frage gestellt, die mir jedoch nicht beantwortet wurde. Warum seid Ihr alle so bös drauf, ist mir wirkklich rätselhaft. Ich hab doch nur nach dem Sinn von 2 Klammern gefragt. Ich hätte nicht gedacht, daß ich hier einen "Krieg" auslöse.
Okay, ich verabschide mich hier aus Eurem Forum, find ich echt schade,
Siro
Finde ich wirklich schade....
BurningWave
06.11.2010, 23:31
Gut ich habe vielleicht etwas zu harte Worte benutzt, ich möchte dich nicht beleidigen.
Jedoch hast du nicht normal gefragt, sondern über C geschimpft. Wenn man das in einem Forum zur C-Programmierung macht, sollte man mit etwas unfreundlicheren Antworten rechnen.
Na sag mal, ich zieh doch nicht den Schwanz ein TobiKa
Da ich aber nicht der Ultimative C Befürworter bin, kommt es mir
so vor als ob ich hier eher unerwünscht bin. Das ist okay, damit kann ich leben. Ich weis garnicht, warum manche Leute so darauf reagieren, wenn mal jemand etwas anderer Meinung ist, zudem habe ich nicht umsonst
meinen Arikel zum "VOID CASTING" mit reingestellt. Ich denke mal, daß
viele von den C-Programmierern damit garnichts anfangen können.
Schau doch bitte nochmal auf meinen Artikel Verfasst am: Gestern um 10:29
Also so ein "Gegner" von C kann ich nun auch wieder nicht sein, wenn
ich mich um solch Dinge kümmere. Kannst Du das nachvolziehen ? dann sage ich nur Hut ab. Irgendwie seid Ihr völlig negativ, wenn ich was gegen
die Programmiersprache C sage. Mein Güte, das ist doch nur eine persönliche Meinung und die ist bei jedem sowieso anders.
Aber ich muss mich doch jetzt nicht rechtfertigen, weil ich C nicht so toll finde. Es gibt viele Sachen die ich nicht so toll finde....
Und wenn ich ausschweife auf die Politik ists noch viel schlimmer :-)
Also lass uns weiter programmieren und auch weiter Proleme welzen,
das gehört einfach dazu.
Siro
ist vergeben, _R2D2
ja, ich gebe zu, daß ich der C-Programmierung doch eher negativ gegenübertrete.
Aber was solls, kein Grund zum streiten sondern eher Erklärungsbedarf.
Ich verstehe da noch so einiges nicht und ich möchte es nicht missen,
dann mal hier im Forum nachzufragen... Und Kritik muss sein,
damit kann ich (und ich hoffe auch Ihr) leben...
Danke Dir _R2D2
Siro
radbruch
07.11.2010, 00:25
Find ich prima wie ihr euch die Hände reicht. Echt vorbildlich :)
Na sag mal, ich zieh doch nicht den Schwanz ein TobiKa
Da ich aber nicht der Ultimative C Befürworter bin, kommt es mir
so vor als ob ich hier eher unerwünscht bin.
Das hier ist ja kein C-Forum, nur der C-Bereich! Und wenn du hier solche Dinger raushaust dann musst du mit ordentlich Gegenwind rechnen!
Fahr mal mit nem Opel auf ein VW Treffen...
Ich denke ich spreche für alle, wenn ich sag, das du mit konstruktiven Beiträgen Herzlich Willkommen bist!
das hat tatsächlich was mit dem Sprachentwurf zu tun. Der Compiler besteht aus Scanner und Parser. Bis wirklich am Ende Byte-Code da steht wird eine komplizierte Sprachgrammatik durchlaufen. Damit diese eindeutig ist muss auch eine eindeutige Sprachsyntax zu Grunde liegen.
Deshalb steht am Anfang des Entwurfs eine eindetige Sprachdefinition.
Die Klammern machen C-Programme finde ich übersichtlicher. Wendet man konsequent Objektorientierung an müssen C++ Programme nicht schwieriger zu lesen sein als Java Programme. Je nachdem wie Parser arbeiten gibt es natürlich ausführungsvorteile bei bestimmten Sprachen. C++ gilt hierbei als sehr schnell. Ich habe Compilerbau zwar mal gemacht, aber es ist nicht mehr so präsent. Nach meinem Verständnis kann es durchaus sein, dass sich die Sprachsyntax hinsichtlich optimierbarkeit durchaus auf die Ausführungsgeschwindigkeit des Bytecodes auswirkt.
Gruß Tim
MeckPommER
08.11.2010, 13:40
Siro, viele deiner Zeilen, wären mir vor 6 Monaten auch direkt aus dem Herzen geschrieben ;-)
Ich habe bis dahin hauptsächlich in Basic, und ASM programmiert und meine ersten Programmiererfahrungen liegen so etwa 30 Jahre zurück.
Da ich für meine Projekte nun ARM7-Controller einsetzen wollte, mußte ich mich wohl oder übel in C einarbeiten. Mein geistiger Kommentar nach einigen Stunden war, das C von einem kichernden Irren erfunden wurde ^^
Man erwartet einfach als erfahrener Programmierer, das sich einem Programmierkonzepte sofort und ohne Umdenken erschließen. Ist das nicht so, geht man davon aus, das es an der Programmiersprache liegt. Die Klammern, = und ==, etc. haben schon ihren Sinn und du als erfahrener Programmierer wirst dir vielleicht auch wie ich zuvor, im Laufe der nächsten Wochen desöfteren mit der flachen Hand an die Stirn klatschen und denken "Ach so ... na, dann ists logisch".
Mittlerweile habe ich mich recht gut eingearbeitet und finde die Wandelbarkeit von C recht genial. Diese Sprache ist mächtig, kann aber dazu verführen, immer kryptischer zu werden. Schlecht im Sinne von unlesbar wird es nur dann, wenn man ein Listing eines Programmierers in die Hand bekommt, der ganz anders tickt als man selber.
C logisch aufgebaut, und das meist auch noch dann, wenn man es auf den ersten Blick nicht sieht ;-)
Man kann schön unabhängige Module schreiben und sie in vielen Projekte wiederverwerten. Bastel dir deine Librarys, mit den Funktionen, die du häufiger brauchst und mache dir das Sprachumfeld angenehmer. Bei mir hat geholfen: einfach nicht aufgeben und danach suchen, warum viele es benutzen :-)
Gruß MeckPommER
Mein geistiger Kommentar nach einigen Stunden war, das C von einem kichernden Irren erfunden wurde ^^
Bei mir war es "was die Typen wohl geraucht haben" :)
So ging es mir mit Eagle übrigens auch.
Hätte ich es nicht beruflich gebraucht, wäre das Programm schon nach kürzester Zeit wieder von der Platte geflogen.
So habe ich dann wochenlang fürchterlich rumgeflucht über das Bedienkonzept, bis ich es dann mal richtig verinnerlicht hatte.
Seit dem mache ich mir gar keine Gedanken mehr darüber und arbeite sogar wirklich gerne damit.
Was C angeht, bin ich momentan noch in der ersten Phase (rumfluchen).
Aber es gibt durchaus noch Hoffnung, daß ich es es demnächst in die nächste Phase (gerne damit arbeiten) schaffe, zumal ich seit kurzer Zeit einen C-erfahrenen Kollegen in unserer Werkstatt sitzen habe, den ich mit Fragen löchern kann. ;)
Gruß
Christopher
BurningWave
08.11.2010, 21:15
Einen kleinen Tipp an alle, die anfangen C mit µCs zu lernen:
Ich finde es ratsamer C++ zu lernen und ein paar Konsolenprogramme zu schreiben, das ist viel anschaulicher, wie mit µCs irgendwas auszuprobieren, da man das Ergebnis sofort sieht. Wenn man C++ kann, kann man C eigentlich auch, da C++ im Prinzip eine Weiterentwicklung von C ist.
Ich finde es ratsamer C++ zu lernen und ein paar Konsolenprogramme zu schreiben, das ist viel anschaulicher, wie mit µCs irgendwas auszuprobieren, da man das Ergebnis sofort sieht.
Mag sein, das mache ich im Moment auch so, hatte vor ewiger Zeit mal MS Visual C++ 6.0 gekauft, was ich jetzt aktuell wieder aktiviert habe.
Hast du irgendwelche Buchempfehlungen ?
Irgendetwas, was auch Spaß zu lesen macht und nicht nur trocken theoretisch daherkommt.
Bisher finde ich meine C /C++ Bücher alle nicht so toll.
Wobei ich "C auf dem Atari ST" irgendwie noch am besten geschrieben finde.
:-k
BurningWave
08.11.2010, 22:56
Nein ich kenne kein gutes Buch, ich habe auch mehrere dicke C++ Bücher, die alle staubtrocken sind. Es gibt aber Bücher wie "C++ für Spieleprogrammierer", in denen die absoluten(!) Grundlagen vermittelt werden. Ich kann mir vorstellen, dass das mehr Spass macht, jedoch habe ich dieses Buch nicht, sondern nur davon gehört.
Fassen wir mal zusammen, daß man C nicht mögen muss, und es gibt durchaus Einiges was man (aus heutiger Sicht) hätte besser machen können...
aber wenn man sich ernsthaft damit auseinandersetzt (bzw. beruflich auseinandersetzen muss), wird man früher oder später auch die Vorteile der Sprache erkennen.
Sich Merkzettel zu schreiben ist für Einsteiger sicherlich sinnvoll, und ich finde es ein bischen schade daß das hier in der Diskussion ein bischen untergegangen ist. Ich hätte auch gleich einen Korrekturvorschlag zu dem geposteten "void casting Infoblatt", denn das ist nicht 100% fehlerfrei:
Diese beiden Zeilen sind nicht äquivalent:
n = (unsigned char*) Testdata;
n = &Testdata;Zunächst mal ist der Typ von TestData ohnehin schon "unsigned char*", denn TestData ist ein Pointer auf das erste Element des Arrays. Der Typecast in der ersten Zeile ist also unnötig. Die zweite Zeile liefert die Adresse von TestData, also die Adresse des Pointers auf das erste Element des Arrays, &TestData hat also den Typ "unsigned char**". Das kann auch durchaus gewünscht sein, aber in 99% der Fälle ist die erste Zeile die richtige.
Hallo Felix G
Danke für deine Rückmeldung auf das "void casting"
ich wollte jetzt nicht extra dafür einen neuen Thread aufmachen, deshalb frage ich gleich hier:
Warum sind die beiden folgenden Zeilen nicht equivalent ?
Wo liegt der Fehler, bzw. was habe ich noch nicht richtig verstanden ?
n = (unsigned char *) TestData; // Adresse setzen
n = &TestData; // oder so, geht auch
Ich habe mal folgendes ausprobiert und bekomme stets das gleiche Ergebnis. bzw. zeigt mein "void pointer n" nach jeder Zeile immer auf die gleiche Adresse.
unsigned char TestData[]={0x00,0x01,0x02,0x03};
void *n;
n = TestData;
n = &TestData;
n = (unsigned char*) TestData;
n = (unsigned int*) TestData;
n = (signed int*) TestData;
n = (int*) TestData;
Es wird lediglich der Zeiger n, welcher vom typ void* ist, auf die Adresse von TestData gesetzt. Die Typwandlung ist hier, wie Du schon sagtest nicht erforderlich, zudem ist ein void pointer generell zu jedem anderen Zeiger kompatibel. Das Entscheidende für mein Verständis waren die folgenden Zeilen: bzw. suchte ich nach einer Möglichkeit ++ bzw -- auf void pointer anzuwenden. Und dies war, logischerweise, nur mit einem entsprechenden casting möglich.
n = (unsigned char *) n+1; // Zeiger + 1 Byte
n = (unsigned short *) n+1; // Zeiger + 2 Bytes
n = (unsigned int *) n+1; // Zeiger + 4 Bytes
++p muss dann so:
n = (unsigned char *) n+1;
oder so:
++(*((char**)(&n)));
codiert werden, wenn es sich um ein Byte Zeiger handeln soll.
mfg. Siro
BurningWave
19.11.2010, 17:37
n = (unsigned char *) n+1;
Mach daraus mal:
((unsigned char *) (n))++;
Das muss funktionieren, wenn n++ nicht geht.
n = TestData;
n = &TestData;
Diese beiden Zeilen sind nicht äquivalent, da letzteres n einen Zeiger auf einen Zeiger, der auf TestData zeigt, zuweist.
Ich habe mal folgendes ausprobiert und bekomme stets das gleiche Ergebnis. bzw. zeigt mein "void pointer n" nach jeder Zeile immer auf die gleiche Adresse.
unsigned char TestData[]={0x00,0x01,0x02,0x03};
void *n;
n = TestData;
n = &TestData;
n = (unsigned char*) TestData;
n = (unsigned int*) TestData;
n = (signed int*) TestData;
n = (int*) TestData;Also diese Zeilen müssen alle das selbe Ergebnis liefern, mit einer Ausnahme:
n = &TestData
Bei dieser Zeile wird n die Adresse von TestData zugewiesen, bei allen anderen der Wert. Bei Typecasts muss man bedenken, daß sie dem Compiler nur vorgaukeln eine Variable hätte einen anderen Typ als es tatsächlich der Fall ist.
Während also die Zeile mit dem & Operator tatsächlich die Adresse von TestData liefert, sagen alle anderen Zeilen nur "behandle TestData so als wäre es ein int*/unsigned char* etc. etc."
[quote=Siro]
n = &TestData
Bei dieser Zeile wird n die Adresse von TestData zugewiesen, bei allen anderen der Wert."
Es wird überall die Adresse von TestData zugewiesen, denn der Wert von TestDate ist bereits die Adresse. Ich glaube du verwechselst da Arrays mit Pointern. Wenn TestData ein Pointer wäre, wäre der Wert von TestData und &TestData verschieden, da &TestData ein Pointer auf den TestData Pointer wäre. In diesem Beispiel ist TestData jedoch ein Array und das & macht rein garnichts.
MfG Mark
BurningWave
20.11.2010, 19:25
In diesem Beispiel ist TestData jedoch ein Array und das & macht rein garnichts.
Das stimmt nicht. In allen Beispielen wird die Adresse von TestData zugewiesen, aber in diesem Fall, die Adresse von der Adresse, also entsteht ein Doppelzeiger vom Typ unsigned char**.
Es wird überall die Adresse von TestData zugewiesen, denn der Wert von TestDate ist bereits die Adresse. Ich glaube du verwechselst da Arrays mit Pointern.Nein, tue ich nicht...
Selbstverständlich ist in diesem Beispiel der Wert von TestData auch schon eine Adresse, aber das spielt keine Rolle. Denn &TestData liefert die Adresse von TestData und das ist eben nicht die in TestData gespeicherte.
Bei Pointern und Typecasts, gerade wenn void* im Spiel ist, sollte man schon wissen was man tut. Denn da kann man sich leicht Bugs einfangen, die ohne JTAG Adapter nur sehr schwer zu entdecken sind.
Alle mir geläufigen C mit und ohne plusplus liefern bei Angabe eines Array OHNE Indexangabe die (Anfangs) adresse des Array, wenn die Zielvariable irgendeine Art von Pointer ist
das ist das "&" in der Tat doppelt gemoppelt.
Brenzlig wird es, wenn ich schreibe z.B
TestData[0] oder &TestData[0]
da ergibt das ampersand einen wesentlichen Unterschied
BurningWave
21.11.2010, 15:59
Wobei &TestData[0] das Gleiche ist, wie TestData, da der []-Operator den Speicherbereich dereferenziert. (Ich bin mir gerade nicht sicher, ob das funktioniert, aber dementsprechend müsste TestData[0] das Gleiche, wie *TestData sein, also der Wert des 1. Elements.)
Denke nicht. *TestData gilt nur (und hat Sinn), wenn TestData ein pointer wäre.
Das Beispiel mit dem "&" wirkt imho verwirrender, als die Sache ist, weil "TestData" als Array definiert ist.
Anschaulicher und verständlicher wäre es, "TestData" sozusagen als normale Variable zu definieren,
unsigned char TestData;
void* n;
n = (void*) TestData // inhalt Testdata
n = (void*) &TestData // adresse TestData
wobei das herum-Casten mit verschiedenen Pointer-type aus der ob. Liste wiederum wirkungslos ist´, wenn "n" ein void-pointer ist. Damit fängt der Compiler im Moment nix an.
Das casten von "n" kriegt Sinn und ist notwendig, wenn ich danach mit "n" irgendwelche operationen ausführen will, also z.B, inkrementieren von "n" selbst oder eben das, wo er hinzeigt.
In diesem Beispiel ist TestData jedoch ein Array und das & macht rein garnichts.
Das stimmt nicht. In allen Beispielen wird die Adresse von TestData zugewiesen, aber in diesem Fall, die Adresse von der Adresse, also entsteht ein Doppelzeiger vom Typ unsigned char**.
Worauf soll &TestData denn zeigen??
Es gibt keine Adresse von Adresse von TestData, da die Adresse von TestData ein rvalue ist und deshalb nicht weiter referenziert werden kann. Der Adress-Operator & macht bei Arrays nichts. Wäre TestArray ein unsigned char* dann würde der Typ von &TestData tatsächlich unsigned char** sein und &TestData würde auf die Adresse von diesem Zeiger ergeben.
MfG Mark
Hallo zusammen,
da muss ich jetzt dem PicNick absolut zustimmen.
Solange ich keine Operation mit dem Zeiger ausführe, ist es völlig unerheblich wie ich diesen Pointer caste. Es wird lediglich festgelegt, auf welche Adresse der Pointer zeigen soll. Ob das ein Char, Int, Array oder was auch immer ist, spielt für den Compiler erstmal keine Rolle. Das "casten" macht so gesehen erstmal überhaupt keinen Sinn und könnte auch Weggelassen werden. Wenn ich aber möchte, daß der "universelle Pointer "VOID" welcher ja zunächst Typenlos ist um ein oder 2 oder 4 Bytes nach der Operation erhöht wird. muss ich ihm natürlich mitteilen
um welchen Datentyp es sich handelt, erst ab da gibt das "Casting" überhaupt einen Sinn.
Wobei ich mir grad selber, beim Schreiben dieses Textes unsicher werde...
wie ist es denn mit "Little Endian" und "Big Endian" ? Zeigt der Pointer dann stets auf das erste Byte ? Dann könnte dies das MSB oder auch das LSB sein. Nehmen wir mal an, ich habe eine 16 Bit Variable. In Intel Notation (Little endian) steht dann das Low Byte z.B. bei Adresse 1000, dann steht das High Byte bei 1001. In Motorola Notation steht dann das High Byte bei 1000 und das Low Byte bei 1001. Wenn ich nun einen Pointer auf diese Variable setze, wo zeigt er dann eigentlich hin ??
Wenn ich nun einen Typecast auf das adressierte Byte mache, und um eins erhöhe, könnte das +1 oder +256 sein.
Ist mir jetzt zu schwierig, muss ich mal drüber schlafen....
muss mich eben revidieren:
zu PicNick
Habe eben nochmal simuliert:
n = (void*) TestData; /* angeblich inhalt Testdata, laut PicNick */
n = (void*) &TestData; /* adresse TestData */
in beiden Fällen wird n auf die Adresse von Testdata gesetzt.
wenn ich nichts falsch gemacht habe....
Siro
Meine Behauptung wird nur stimmen, wenn "TestData" KEIN array ist
Little / Big Endian:
Ein Pointer zeigt immer auf das erste memory-Byte.
Es ist nur immer der Aufbau des Pointer und die Bearbeitung der Daten entsprechend.
oberallgeier
22.11.2010, 09:00
... Es ist nur immer der Aufbau des Pointer und die Bearbeitung der Daten entsprechend ...Das eine oder andere hier verstehe ich ja oder kann es nacharbeiten. Aber der Thread gibt mir mehr und mehr die Zuversicht, dass ich C praktisch garnicht kann. Zumindest über weite Strecken. Immerhin scheinen jede Menge bisher unbenützter Seiten in meinem Kernighan/Ritchie doch nicht für die Tonne zu sein.
Aber eins ist auch klar: Schuld sind die Engländer, die nicht nur auf der falschen Seite autofahren, sondern auch die Eier am dünnen Ende aufknicken - und das noch aus Glaubensgründen.
Hier mal ein kleiner Auszug aus dem C99-Standard
6.5.3.2 Address and indirection operators
Constraints
1 The operand of the unary & operator shall be either a function designator, the result of a
[] or unary * operator, or an lvalue that designates an object that is not a bit-field and is
not declared with the register storage-class specifier.
2 The operand of the unary * operator shall have pointer type.
Semantics
3 The unary & operator yields the address of its operand. If the operand has type ‘‘type’’,
the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator,
neither that operator nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and the result is not an
lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor
the unary * that is implied by the [] is evaluated and the result is as if the & operator
were removed and the [] operator were changed to a + operator. Otherwise, the result is
a pointer to the object or function designated by its operand.
4 The unary * operator denotes indirection. If the operand points to a function, the result is
a function designator; if it points to an object, the result is an lvalue designating the
object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an
invalid value has been assigned to the pointer, the behavior of the unary * operator is
undefined.
Da steht viel, aber eben nicht, daß sich der & Operator bei einem Array anders verhalten sollte als bei einem normalen Pointer. Das mag zwar bei den meisten Compilern so sein, aber es steht eben nicht im Standard (oder wenn, habe ich die entsprechende Stelle übersehen). Wenn man also in seinem Programm davon ausgeht, daß "ArrayName" und "&ArrayName" den selben Wert liefern, funktioniert es vielleicht nicht mehr wenn man auf einen anderen Compiler umsteigt.
PicNick schrieb:
Meine Behauptung wird nur stimmen, wenn "TestData" KEIN array ist
Da muss ich ihm vollkommen zustimmen, ich habe es eben mit dem IAR Compiler getestet,
mit folgenden verblüffenden Resultaten:
--------------------------------------------------------------
wenn TestData ein Array ist: unsigned char TestData[4];
n = (void*) TestData; /* Adresse TestData */
n = (void*) TestData[0]; /* Inhalt Testdata */
n = (void*) &TestData; /* Adresse TestData */
n = (void*) *&TestData; /* Adresse TestData */
--------------------------------------------------------------
wenn TestData kein Array ist: unsigned char TestData;
n = (void*) TestData; /* Inhalt TestData */
n = (void*) TestData[0]; /* geht natürlich nicht */
n = (void*) &TestData; /* Adresse TestData */
n = (void*) *&TestData; /* Inhalt TestData */
--------------------------------------------------------------
Siro
Bei sowas
++(*((char**)(&n)));
glaub ich halt immer, jemand hat die Tastatur mit dem Scheuerbesen abgewischt.
Das ist imho reiner Schamanismus.
Andere Meinungen sind aber durchaus zulässig, ich wollt' es nur gesagt haben.
Hier mal ein kleiner Auszug aus dem C99-Standard
6.5.3.2 Address and indirection operators
Constraints
1 The operand of the unary & operator shall be either a function designator, the result of a
[] or unary * operator, or an lvalue that designates an object that is not a bit-field and is
not declared with the register storage-class specifier.
2 The operand of the unary * operator shall have pointer type.
Semantics
3 The unary & operator yields the address of its operand. If the operand has type ‘‘type’’,
the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator,
neither that operator nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and the result is not an
lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor
the unary * that is implied by the [] is evaluated and the result is as if the & operator
were removed and the [] operator were changed to a + operator. Otherwise, the result is
a pointer to the object or function designated by its operand.
4 The unary * operator denotes indirection. If the operand points to a function, the result is
a function designator; if it points to an object, the result is an lvalue designating the
object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an
invalid value has been assigned to the pointer, the behavior of the unary * operator is
undefined.
Da steht viel, aber eben nicht, daß sich der & Operator bei einem Array anders verhalten sollte als bei einem normalen Pointer. Das mag zwar bei den meisten Compilern so sein, aber es steht eben nicht im Standard (oder wenn, habe ich die entsprechende Stelle übersehen). Wenn man also in seinem Programm davon ausgeht, daß "ArrayName" und "&ArrayName" den selben Wert liefern, funktioniert es vielleicht nicht mehr wenn man auf einen anderen Compiler umsteigt.
Ok, ich geb mich geschlagen. Du hast also Recht. Hab gerade auch etwas rumgesucht und erfahren, dass ein Array sehr wohl ein lvalue ist, was alles, was ich oben gesagt habe, zunichte macht.
MfG Mark
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.