Hallo Community,
leider bin ich kein "C" Profi und stelle euch nun diese Frage, ich komm
einfach nicht drauf wie ich das Problem lösen könnte..
Kurz eine Erklärung:
Ich bräuchte ein "SUB_ARRAY_SIZE" makro welches mir die Größe eines
struct innerhalb eines anderen structs zurückgeben würde.
Beispiel:
1
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
2
3
/* ___ Menu defines ___ */
4
typedefvoid(*MenuFnct)(void);
5
6
structDisplayElements// Elements to display on TFT screen
7
{
8
uint8_tposx;// "x" element position (the left upper corner)
9
uint8_tposy;// "y" element position (the left upper corner)
10
uint8_tsizex;// "x" element size
11
uint8_tsizey;// "y" element size
12
uint8_ttype;// 1=button, 2=text
13
charText[10];// display text for element (just possible on some grafic_type elements!)
14
15
};
16
structMenuEntry
17
{
18
charText[20];// Menu caption
19
DisplayElements*elements;// Elements to draw on TFT
20
MenuFnctFunction;// function to call on activate/click/open
Der Aufruf von "ARRAY_SIZE( BaseMenu )" funktioniert wunderbar (sollte
ja auch so sein)
Aber ich bräuchte eben vom struct "MenuEntry" die Größe der "elements"
da ich in einer loop Schleife alle "DisplayElements" abarbeiten möchte.
Im Prinzip sowas:
De Zordo P. schrieb:> Wie Programmiert man das? Werde noch wahnsinnig.. :D
Das geht nicht. "elements" ist nur ein Pointer auf eine Speicherstelle,
da ist keinerlei Information enthalten, wie viele Elemente dort
tatsächlich zu finden sind. Du musst in deinem "struct MenuEntry" eine
extra Variable vorsehen, in die du die Größe des Arrays packst.
Das ARRAY_SIZE Makro funktioniert nur mit Arrays, deren Größe dem
Compiler bekannt ist, und deren Typ nicht zB "DisplayElements*" sondern
"DisplayElements [3]" ist...
Georg G. schrieb:> Eine gängige Lösung ist, die Liste mit einem NULL Pointer zu schließen.
..und dann liest man immer "DisplayElements" große Häppchen ein bis man
zum NULL Wert kommt oder?
Also konkret ein struct vom Typen "DisplayElements" zur Laufzeit füllen,
dann um "DisplayElements" weiterspringen bis NULL?
Georg G. schrieb:> Eine gängige Lösung ist, die Liste mit einem NULL Pointer zu> schließen.
Das geht hier aber nicht, weil das "elements" Array Objekte vom Typ
DisplayElements enthält, welches kein Pointer-Typ ist.
De Zordo P. schrieb:> ..und dann liest man immer "DisplayElements" große Häppchen ein bis man> zum NULL Wert kommt oder?
Tja, leider gibt es keinen NULL-Wert für DisplayElements. Du könntest
ein extra "DisplayElements" Objekt an das Ende des Arrays packen, dessen
Felder so gesetzt sind dass es als "Ende-Marker" erkannt wird; zB "type"
auf 0.
Programmierer schrieb:> Georg G. schrieb:>> Eine gängige Lösung ist, die Liste mit einem NULL Pointer zu>> schließen.> Das geht hier aber nicht, weil das "elements" Array Objekte vom Typ> DisplayElements enthält, welches kein Pointer-Typ ist.>> De Zordo P. schrieb:>> ..und dann liest man immer "DisplayElements" große Häppchen ein bis man>> zum NULL Wert kommt oder?> Tja, leider gibt es keinen NULL-Wert für DisplayElements. Du könntest> ein extra "DisplayElements" Objekt an das Ende des Arrays packen, dessen> Felder so gesetzt sind dass es als "Ende-Marker" erkannt wird; zB "type"> auf 0.
Könntest du mir ein kurzes, konkretes Beispiel zeigen?
Ich bin wieder mal total vorm Berg.. :O
Ich vermute mal so in etwa?
Doch wie komme ich genau auf die Länge ohne diese im struct als eigene
Variable mitzugeben?
Meine "Auswertroutine" die den struct parsed sollte folgendermaßen
aussehen (nur als Beispielcode, dieser funktioniert klar so nicht!):
/* "elements" müsste hier auf das nächste array im struct springen */
14
..
15
}
16
}
17
}
Vom Prinzip her ist es mir, glaube ich, klar! Aber wie coded man das
dann auch? Deferenzieren und Referenzieren liegen mir noch nicht so
ganz.. :(
Danke!
Georg G. schrieb:> Eine gängige Lösung ist, die Liste mit einem NULL Pointer zu schließen.
Dazu müsste er aber erst mal ein Pointer Array haben. Was er nicht hat.
Was aber ginge, wäre zb die Vereinbarung, dass ein DisplayElement mit
einer Position von 255 / 255 (oder anderen Zahlen, die sonst nicht
vorkommen werden) das letzte (nicht mehr darzustellende) Element im
Array ist.
Natürlich muss sicher gestellt sein, dass der Programmierer keinen
Fehler macht, und in allen derartigen Beschreibungen, das jeweils
abschliessende Element einfügt.
Zum einen kann man das mit dem ARRAY_SIZE Makro so hindrehen, dass einem
der Compiler die lästige Arbeit des Nachziehens der Konstante abnimmt,
wenn man die Darstellung ändert. Zum anderen ist es schwerer, die Angabe
zu vergessen, weil dann die Anzahl der Initialisierungen nicht mit der
Strukturdefinition übereinstimmt. Und weniger Platz benötigt es auch.
Der Nachteil ist natürlich, dass man auf eine bestimmte maximale Anzahl
an Display-Elementen limitiert ist.
müssen raus.
WEnn du hier einen const Fehler kriegst, dann kann die Lösung nicht
darin liegen, dass du das const wegcastest, sondern darin, dass du hier
1
structMenuEntry
2
{
3
charText[20];// Menu caption
4
constDisplayElements*elements;// Elements to draw on TFT
5
MenuFnctFunction;// function to call on activate/click/open
6
};
die notwendige const-Eigenschaft zusicherst.
Ihr Castet mir alle ein bischen zu viel und vor allen Dingen zu
leichtsinnig.
Gerade das Umcasten von Pointern ist eine gefährliche Sache!
Karl Heinz schrieb:> WEnn du hier einen const Fehler kriegst, dann kann die Lösung nicht> darin liegen, dass du das const wegcastest, sondern darin, dass du hier>
1
>structMenuEntry
2
>{
3
>charText[20];// Menu caption
4
>constDisplayElements*elements;// Elements to draw on TFT
5
>MenuFnctFunction;// function to call on
6
>activate/click/open
7
>};
8
>
> die notwendige const-Eigenschaft zusicherst.>> Ihr Castet mir alle ein bischen zu viel und vor allen Dingen zu> leichtsinnig.> Gerade das Umcasten von Pointern ist eine gefährliche Sache!
Sorry, bin recht neu. Aber habe ich mir gemerkt!
Vielen Dank!
Karl Heinz schrieb:> Was aber ginge, wäre zb die Vereinbarung, dass ein DisplayElement mit> einer Position von 255 / 255 (oder anderen Zahlen, die sonst nicht> vorkommen werden) das letzte (nicht mehr darzustellende) Element im> Array ist.
würde ich gerne mit
1
if(type!=0)..
lösen.
"Type 0" muss ich nicht haben, kann also gerne als "EOF" benutzt werden.
> Natürlich muss sicher gestellt sein, dass der Programmierer keinen> Fehler macht, und in allen derartigen Beschreibungen, das jeweils> abschliessende Element einfügt.
Das sollte kein Problem darstellen, einmal eingefügt bleibt die
"EOF"-Zeile im Code und wird nicht mehr verändert.
>> Hmm. Ich denke, eine explizite Längenangabe im struct MenuEntry>
Ok, das mache ich jetzt so! Mit dem "ARRAY" Makro damit bei der
Umstellung der Menüstruktur nicht an mehreren Stellen
Variablen/Konstanten umgeändert werden müssen.
1
structMenuEntry
2
{
3
charText[20];// Menu caption
4
uint8_tdisplay_struct_size;// Holds the size of the display_struct
5
constDisplayElements*elements;// Elements to draw on TFT
6
MenuFnctFunction;// function to call on activate/click/open
De Zordo P. schrieb:> Sorry, bin recht neu. Aber habe ich mir gemerkt!
Wenn du etwas const machst, dann musst du das auch durchziehen!
Es ist recht sinnfrei, Variablen als 'const' anzulegen, und dann im
kompletten Code das const wieder wegzucasten. Da hättest du dir das
const bei den Variablen auch gleich sparen können.
Das ist ungefähr so sinnvoll, wie sich ein blaues Auto zu kaufen, nur um
dann nach und nach alle Teile auf rot umzulackieren.
Karl Heinz schrieb:> De Zordo P. schrieb:>>> Sorry, bin recht neu. Aber habe ich mir gemerkt!>> Wenn du etwas const machst, dann musst du das auch durchziehen!> Es ist recht sinnfrei, Variablen als 'const' anzulegen, und dann im> kompletten Code das const wieder wegzucasten. Da hättest du dir das> const bei den Variablen auch gleich sparen können.>> Das ist ungefähr so sinnvoll, wie sich ein blaues Auto zu kaufen, nur um> dann nach und nach alle Teile auf rot umzulackieren.
Is es richtig so viel als möglich als "const" zu definieren um flash zu
sparen? Denn dann sollte ich auch
De Zordo P. schrieb:> Is es richtig so viel als möglich als "const" zu definieren um flash zu> sparen?
Wenn es auf deinem nicht genannten Compiler so ist, dass er 'const'
Dinge automatisch ins Flash legt, dann kann es unter Umständen sogar
lebenswichtig sein, dass du das const durchziehst!
Denn wenn auf deinem System die Zugriffe ins Flash technisch anders
durchzuführen sind als Zugriffe ins normale RAM, dann muss der Compiler
an den verwendenden Stellen auch wissen, dass da ein Pointer ins Flash
zeigt und nicht ins RAM um dann die jeweils technisch richtige
Zugriffsmethode zu benutzen!
> Das ist, soweit ich das verstanden habe auch Müll den ich beseitigen> sollte!?
Unbedingt.
Du musst dir im klaren sein, dass ein derartiger Cast das komplette
Typ-System des Compilers aushebelt! Dein Compiler würde dich gerne
warnen, dass hier unter Umständen etwas grauslich schief gehen kann. Mit
dem Cast sagst du dem Compiler "Halt die Klappe!". Nur: das beseitigt
kein potentielles Problem, wenn du dem Compiler den Mund verbietest. Ein
mögliches Problem ist ja trotzdem immer noch vorhanden, das löst sich ja
deswegen nicht in Luft auf nur weil die Anweisung kommt, nicht darüber
zu reden.
Wenn ich ein Buch habe, auf das ich aufpasse und in das ich keine
Anmerkungen geschrieben haben will (das also effektiv const ist), dann
will ich von dir die Zusicherung haben, dass du auch nichts ins Buch
hineinschreibst! Nichts anders macht ein const in einer
Argumentschnittstelle
Dieses const ist hier zu lesen als: Egal auf welches struct MenuEntry
der Pointer menu auch zeigt, ich werde die dort gespeicherten Daten
nicht verändern! Versuche ich das im Code trotzdem ...
dann wird mir der Compiler auf die Finger klopfen und das nicht
zulassen.
Und genau diese Zusicherung will ich von einer Funktion sehen, der ich
etwas übergebe, was const ist.
Ist der Unterschied der, dass bei der *1.Definition*:
1. Ein lokales struct vom Typ "MenuEntry" angelegt wird und ich
dadurch immer die "Offsets" mit "Menu[x]" mit angeben muss?
2. Dass der Compiler mir dann auch das RAM innerhalb der Funktion
"doppelt" belegt?
..und bei der *2.Definition*:
1. Es wird nur mit Pointern (dereferenziert) gearbeitet --> kein
zusätzlicher Speicherverbrauch da nur die Adresse übergeben wird?
2. Kann ich mit der Inkrementierung der Pointeradresse um das "sizeof(
DisplayElements )" weiter zum nächsten Array springen kann?
Viele Frage, doch ich muss es genau wissen! :)
Danke!
De Zordo P. schrieb:> Welche Unterschiede ziehen eigentlich folgende Definitionen der Funktion> "DrawMenu" mit sich?
Gar keinen. Höchstens dokumentarischen, weil man im Protoypen sieht,
dass die Funktion gerne einen Pointer bekommen würde auf etwas, das sie
wie ein Array behandelt. Aber technisch gibt es keinen Unterschied.
Die [] Schreibweise ist nur syntaktischer Zucker für Leute, die mit der
Pointer Schreibweise nicht klar kommen.
Karl Heinz schrieb:> Wenn es auf deinem nicht genannten Compiler so ist, dass er 'const'> Dinge automatisch ins Flash legt, dann kann es unter Umständen sogar> lebenswichtig sein, dass du das const durchziehst!
Als Compiler bzw. Entwicklungsumgebung verwende ich gerade meinen
Arduino. Ansonsten immer GCC der mit dem Atmel Studio mitgeliefert wird.
Ich weiß aber nicht genau ob diese das "const" als Optimierung ansehen?
Fakt ist, dass beim Kompilieren (Arduino) die größe des Programms mit
den "const" Angaben abgenommen hat. Nur um einige 10Bytes.. Aber
vielleicht landet dann mehr auf dem Stack/RAM?
Da der Speicher, also Flash und RAM bei den Mikrocontrollern sowiso
nicht gerade rießig ist wollte ich kompakten C-Code generieren,
angefangen bei den Deklarationen der Variablen.
Ist das ein guter Ansatz oder soll ich den einfach "fallen" lassen?
>> Das ist, soweit ich das verstanden habe auch Müll den ich beseitigen>> sollte!?>> Unbedingt.
OK, das nehme ich mir zu Herzen und schreibe die paar Zeilen gleich um
damit ich den Compiler nicht mehr "Überreden" muss meinen Müll
auszuführen.. ;)
Karl Heinz schrieb:> Die [] Schreibweise ist nur syntaktischer Zucker für Leute, die mit der> Pointer Schreibweise nicht klar kommen.
Das klingt nach mir.. ;) Aber ich setzte mich daran die Pointer aus dem
FF zu verstehen. Dauert nur ein wenig da es als Neuling doch etwas
Verwirrung stiftet..
De Zordo P. schrieb:> Als Compiler bzw. Entwicklungsumgebung verwende ich gerade meinen> Arduino. Ansonsten immer GCC der mit dem Atmel Studio mitgeliefert wird.> Ich weiß aber nicht genau ob diese das "const" als Optimierung ansehen?
Dann sparst du durch das const erst mal kein RAM ein.
Hier wird const so benutzt, wie es von der Sprache her vorgesehen ist.
const markiert, dass sich der Wert einer Variablen während ihres
Lebenszykluses nicht verändern wird. Kennt daher der Compiler diesen
Wert, dann kann er überall den Wert der Variablen direkt anstelle der
Variablen einsetzen. Unter Umständen führt das dazu, dass die Variable
überhaupt nicht mehr gebraucht wird und daher vom Optimierer komplett
entfernt wird.
> Fakt ist, dass beim Kompilieren (Arduino) die größe des Programms mit> den "const" Angaben abgenommen hat.
Aber nicht bei diesen Arrays. Bei
1
staticconstinti=8;
2
3
voidloop()
4
{
5
serial.print(i);
6
}
kann es sein, dass das Programm ein bischen kleiner wird, weil wie
gesagt der Compiler das zu dem hier
1
voidloop()
2
{
3
serial.print(8);
4
}
umformen kann, da er ja den Wert von i kennt, das i sonst nirgends mehr
vorkommt und das const die Zusicherung gibt "An den 8 wird sich auch
nichts ändern, großes Indianer-Ehrenwort".
> Da der Speicher, also Flash und RAM bei den Mikrocontrollern sowiso> nicht gerade rießig ist wollte ich kompakten C-Code generieren,> angefangen bei den Deklarationen der Variablen.
Du scheinst mir da eine gefährliche Mischung an Halbwissen zu haben.
Karl Heinz schrieb:> "An den 8 wird sich auch> nichts ändern, großes Indianer-Ehrenwort".
Glaub ich dir gerne! ;)
Es wird sicherlich eine "kleine" Optimierung gegeben haben wie du
bereits erwähnt hast.
Diese kann man aber nicht global sehen, somit versuche ich "const" als
"const" zu verwenden und nicht als "Speicheroptimierungsflag". ;)
Karl Heinz schrieb:> Du scheinst mir da eine gefährliche Mischung an Halbwissen zu haben.
Leider reicht das "Basiswissen Schule" nicht aus um alle Details genau
zu kennen.. :(
De Zordo P. schrieb:> Wie gehe ich das am besten an?
Genau gleich.
Tu dir selbst einen Gefallen und besorg dir ein C-Buch.
Die Pointer-Array Dualität ist in C einer der Grundpfeiler erfolgreichen
programmierens. Und auch wenn das in C++ ein wenig zurückgedrängt wird,
bedeutet das auch in C++ nicht, dass es sich um ein unwesentliches
Detail handelt, über das man nicht Bescheid wissen muss.
Karl Heinz schrieb im Beitrag #3882155:
> Tu dir selbst einen Gefallen und besorg dir ein C-Buch.
Kann und werde ich machen, doch zuerst muss es bei mir Zuhause warm
werden, dazu muss mein Controllerboard mitsamt dem Code funktionieren..
;)
Karl Heinz schrieb im Beitrag #3882155:
> Genau gleich.
Hm...
Also wenn ich richtig verstehe, bedeutet das soviel, dass durch die
"[]"-Schreibweise nichts anderes gemacht wird als die Adresse auf die
der Pointer zeigt geändert wird? Und zwar immer in "struct MenuEntry"
Schritten? oder?
Ich könnte also den Pointer "*Menu" um das "sizeof(MenuEntry)"
inkrementieren und lande im nächsten Array des Menüs? :O
Patrick Z. schrieb:> Karl Heinz schrieb im Beitrag #3882155:>> Tu dir selbst einen Gefallen und besorg dir ein C-Buch.>> Kann und werde ich machen, doch zuerst muss es bei mir Zuhause warm> werden, dazu muss mein Controllerboard mitsamt dem Code funktionieren..> ;)>> Karl Heinz schrieb im Beitrag #3882155:>> Genau gleich.>> Hm...> Also wenn ich richtig verstehe, bedeutet das soviel, dass durch die> "[]"-Schreibweise nichts anderes gemacht wird als die Adresse auf die> der Pointer zeigt geändert wird? Und zwar immer in "struct MenuEntry"> Schritten? oder?> Ich könnte also den Pointer "*Menu" um das "sizeof(MenuEntry)"> inkrementieren und lande im nächsten Array des Menüs? :O
Welchen Teil von 'genau gleich' hast du nicht verstanden
In C ist die Array-Index Operation gemeinsam mit Pointer-Arithmetik
genau so definiert, dass das geht. Daher ist es auch so essentiell
wichtig, diese Dinge von der Pieke auf zu lernen.
Karl Heinz schrieb:>> Also wenn ich richtig verstehe, bedeutet das soviel, dass durch die>> "[]"-Schreibweise nichts anderes gemacht wird als die Adresse auf die>> der Pointer zeigt geändert wird?
Nein.
Es gibt keinen technischen Unterschied zwischen
Karl Heinz schrieb:> In C ist die Array-Index Operation gemeinsam mit Pointer-Arithmetik> genau so definiert, dass das geht.
Ja, das habe ich verstanden.. ABER wäre es möglich auch den Pointer
direkt zu manipulieren?
Ich weiß das ist KEINE gute Idee da man damit auch ins "Nichts"
verweisen kann... :)
Patrick Z. schrieb:> Ja, das habe ich verstanden.. ABER wäre es möglich auch den Pointer> direkt zu manipulieren?
Natürlich.
Aber auch hier wieder. DU inkementierst einfach.
Da braucht es keinen sizeof. Der COmpiler weiss ja, dass 'Menu' (oder
'tmp') auf ein struct MenuEntry zeigt. Pointer Arithmetik ist so
definiert, dass in
1
T*pPointer;// T sei irgendein Datentyp
2
3
pPointer++;
4
pPointer+=2;
5
pPointer.....
die sizeof(T) automatisch immer mit eingerechnet wird. Darum brauchst du
dich daher nicht kümmern und willst es auch gar nicht. Das ist ja auch
einer der Gründe, warum du nicht einfach sagst "Das ist ein Pointer"
sondern "Das ist ein Pointer auf ein struct Menu" oder "Das ist ein
Pointer auf int" oder "Das ist ein Pointer auf ..."
Karl Heinz schrieb:> Das ist ja auch> einer der Gründe, warum du nicht einfach sagst "Das ist ein Pointer"> sondern "Das ist ein Pointer auf ein struct Menu" oder "Das ist ein> Pointer auf int" oder "Das ist ein Pointer auf ..."
Und letzten Endes ist ja auch die Index Operation in C so definiert:
1
a[i] <==> *( a + i )
genau das macht der Compiler, wenn du
1
inta[5];
2
3
for(i=0;i<5;i++)
4
serial.println(a[i]);
schreibst. Er formt als erstes den Ausdruck 'a[i]' in die äquivalente
Pointer Schreibweise '*(a+i)' um. Der Name des Arrays fungiert
(alleinstehend) als die Startadresse des Arrays. Dazu wird noch der
Offset i addiert (unter Berücksichtung der sizeof dessen, worauf der
Pointer zeigt) und mit der so erhaltenen Speicheradresse wird
dereferenziert.
Karl Heinz schrieb:> Da braucht es keinen sizeof. Der COmpiler weiss ja, dass 'Menu' (oder> 'tmp') auf ein struct MenuEntry zeigt. Pointer Arithmetik ist so> definiert, dass in T * pPointer; // T sei irgendein Datentyp>> pPointer++;> pPointer += 2;> pPointer .....> die sizeof(T) automatisch immer mit eingerechnet wird. Darum brauchst du> dich daher nicht kümmern und willst es auch gar nicht. Das ist ja auch> einer der Gründe, warum du nicht einfach sagst "Das ist ein Pointer"> sondern "Das ist ein Pointer auf ein struct Menu" oder "Das ist ein> Pointer auf int" oder "Das ist ein Pointer auf ..."
Das ist eine PERFEKTE Antwort! :)))
Vieeeelen vieeeelen Dank!
Karl Heinz schrieb:> Karl Heinz schrieb:>>> Das ist ja auch>> einer der Gründe, warum du nicht einfach sagst "Das ist ein Pointer">> sondern "Das ist ein Pointer auf ein struct Menu" oder "Das ist ein>> Pointer auf int" oder "Das ist ein Pointer auf ...">>> Und letzten Endes ist ja auch die Index Operation in C so definiert:>>
1
> a[i] <==> *( a + i )
2
>
>> genau das macht der Compiler, wenn du>
1
>inta[5];
2
>
3
>for(i=0;i<5;i++)
4
>serial.println(a[i]);
5
>
> schreibst. Er formt als erstes den Ausdruck 'a[i]' in die äquivalente> Pointer Schreibweise '*(a+i)' um.
Karl Heinz,
darf ich dich bitten mir einen konkreten Buchvorschlag zum Thema "C",
vielleicht mit Schwerpunkt µC, ist aber auch nicht so wichtig, zu geben?
Ich will und muss mich einlesen. Ich möchte dann noch weitere Projekte
angehen welche dann immer komplizierter werden und ich dann immer mehr
"auf dem Schlauch" stehen werde..
Patrick Z. schrieb:> darf ich dich bitten mir einen konkreten Buchvorschlag zum Thema "C",> vielleicht mit Schwerpunkt µC, ist aber auch nicht so wichtig, zu geben?
Das musst du sowieso trennen. Das sind 2 verschiedene Dinge.
Das eine ist die Programmierung mit der Programmiersprache C.
Das andere ist die µC Programmierung.
Die beiden haben natürlich irgendwo Berührungspunkte. Trotzdem ist es
sinnvoll die Dinge zu trennen. Denn C funktioniert (bis auf Ausnahmen
:-) überall gleich. Abgesehen von ein paar Details wie Bytegrößen von
Datentypen und noch ein paar anderen Dingen, ist die Logik der Sprache,
wie sie funktioniert und was die einzelnen Dinge bedeuten vom µC bis zum
Supercomputer überall identisch.
Eine ziemlich vernünftige Empfehlung ist, sich die ersten C Hörner erst
mal auf dem PC abzustossen und dort C in den Grundzügen zu lernen. Der
Vorteil ist, dass es da massenhaft Literatur gibt (manche mit
zweifelhaftem Lernwert), bei denen aber ausnahmslos auf einem PC erst
mal alle Beispiele aus dem Buch funktionieren werden. Der Grund dafür
ist einfach: C definiert ja auch ein gewisses Verhalten gegenüber der
Umwelt. Ein printf funktioniert auf allen Systemen, die eine Konsole
haben immer gleich und zaubert eine Ausgabe auf die Konsole. Nur: Auf
einem µC hat man meistens keine Konsole, sondern muss sich die ebenfalls
erst mal selber programmieren. Kurz und gut: Die in C-Büchern
vorausgesetzte Umgebung existiert auf einem PC bereits und die C-Systeme
kommen so daher, dass sie auch genau so funktioniert, wie im C-Standard
(und damit auch in den Büchern) beschrieben. Auf einem µC ist das aber
nicht so.
Dazu kommt noch, dass man auf einem PC viel bessere Debug-Möglichkeiten
hat, als auf einem µC. D.h der Lernfortschritt ist auf dem PC in
derselben Zeit viel höher als auf einem µC, weil man sich nicht mit
µC-spezifischen Dingen rumschlagen muss wie zb die banale Ausgabe von
Werten auf einem LCD.
Erst dann, wenn man die C Programmierung sei leidlich auf dem PC
beherrscht, ist es sinnvoll auf einen µC zu wechseln und sich den
Spezialitäten zu widmen, die das besondere Umfeld µC so mit sich bringt.
Das Wissen, das man sich auf dem PC erwworben hat, ist ja nicht
verloren. Die Sprache an sich funktioniert ja auf dem µC gleich zum PC.
Weg fällt die Art und Weise, wie sich ein Programm nach aussen bemerkbar
machen kann, dafür gibt es dann eben neue spezielle Dinge, die auf dem
PC wieder nicht so wichtig sind, wie zb die Beherrschung von
Bitoperationen.
C Bücher gibt es viele.
Der Klassiker "Kernighan & Ritchie, Programmieren in C" wird gerne
genommen. Aber am besten ist es wohl, wenn du in eine Buchhandlung gehst
(oder Bibliothek) und einfach mal in ein paar Büchern schmökerst, mit
wessen Sprache du am besten zurecht kommst.
Es wird auch nicht so sein, dass du nach Durcharbeiten des Buches zu
einem C-Spezialisten wirst. Da gibt es immer noch viele Feinheiten. Aber
es ist schon mal viel einfacher, wenn man nicht an allen Ecken und Enden
bei Adam und Eva anfangen muss.
Karl Heinz schrieb:> Es wird auch nicht so sein, dass du nach Durcharbeiten des Buches zu> einem C-Spezialisten wirst. Da gibt es immer noch viele Feinheiten. Aber> es ist schon mal viel einfacher, wenn man nicht an allen Ecken und Enden> bei Adam und Eva anfangen muss.
Das meinte ich.. :-)
Vielen herzlichen Dank nochmal!
Jetzt versuche ich die "SPI-Grafikroutine" zu Programmieren, dann die
automatische grafische Generierung der Oberfläche inkl. der Auswertung
der Touch-Eingaben und dann hoffen wir mal, dass es langsam wieder warm
wird.. :-P
Evtl. erstelle ich dann wieder ein neues Thema sobald ich wieder an die
Grenzen meines "C-Universe" komme..