Hallo Leute!
Ich les jetzt schon ne Weile die Beträge zum Thema sizeof in diesen
Foren durch, aber irgendwie werde ich daraus nicht schlau.
Ich habe eine Funktion bla, in der ein Array initialisiert wird (größe
ändert sich), welches dann einer anderen Funktion übergeben wird:
void bla(){
....
uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};
...
machwas(werte);
...
}
machwas(uint8_t werte[]){
uint8_t akt_wert;
uint8_t anz = sizeof(werte);
for(akt_wert=0; akt_wert < anz ; akt_wert++){
...
}
...
}
Alles was ich will ist, dass die for-Schleife vom ersten bis zum letzten
Element des Arrays "werte" durchläuft.
Ich hab die gleichen Probleme, wie
Beitrag "Re: Größenangabe von Feldern"
oder
Beitrag "Re: sizeof Frage" ,dass
ich nur "schwachsinnige" Werte wie "0x02" oder "0x01" als Rückgabewert
erhalte.
Wenn ich in der Funktion "bla" nach der Initialisierung des Arrays
"sizeof(werte)" eingebe, erhalte ich als Rückgabewert die richtige
Anzahl von Elementen im Array.
Könnt ihr mir weiterhelfen?
Vielen Dank!
Gruß
Phil
Phil wrote:
> void bla(){> ....> uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};
Du weißt, dass die Werte zur Laufzeit zugewiesen werden, ja? Jedesmal
beim Eintritt in die Funktion.
> machwas(uint8_t werte[]){
Das ist äquivalent zu
machwas(uint8_t *werte) {
...
da alle Felder (und Funktionen) in C als Zeiger an aufgerufene
Funktionen übermittelt werden. Damit sollte dir auch klar sein, warum
sizeof in machwas() eine 2 ergibt.
> Alles was ich will ist, dass die for-Schleife vom ersten bis zum> letzten Element des Arrays "werte" durchläuft.
ich vermute (bzw. bin mir eigentlich ziemlich sicher) dass sizeof()
gleich bei der Compilezeit berechnet wird.
Das einzige was mir dazu einfällt wäre:
machwas (uint8_t *pWerte, unint8_t size) {
...
}
und dann der Aufruf:
machwas (werte, sizeof(werte));
"machwas(werte, sizeof werte);"
Das ist ne gute Lösung! ;)
Aber gibt es trotzdem eine Möglichkeit die Größe des Arrays, also die
Anzahl der Elemente, in der Funktion "machwas" "herauszubekommen"?!?
> Aber gibt es trotzdem eine Möglichkeit die Größe des Arrays, also die> Anzahl der Elemente, in der Funktion "machwas" "herauszubekommen"?!?
Nein, ausser du reservierst einen Wert als Endezeichen (Bei Strings ist
das 0x00)
Phil wrote:
> Aber gibt es trotzdem eine Möglichkeit die Größe des Arrays, also die> Anzahl der Elemente, in der Funktion "machwas" "herauszubekommen"?!?
Nein. Bitte denk doch mal nach: diese Funktion bekommt vom dem ganzen
Array nur einen Zeiger auf den Anfang übergeben. Wie, bitteschön, soll
sie denn dann noch an die Größeninformation herankommen?
>Aber gibt es trotzdem eine Möglichkeit die Größe des Arrays, also die>Anzahl der Elemente, in der Funktion "machwas" "herauszubekommen"?!?
Nein.
>machwas(uint8_t werte[]){
werte[] ist ein ptr auf uint8_t. Irgendeine Größenangabe wird da nicht
übergeben.
Nimm die Lösung von Roland.
Stefan
@Phil
>"machwas(werte, sizeof werte);">Das ist ne gute Lösung! ;)
Aber irgendwie glaube ich nciht, dass sie funktionieren wird.
>Aber gibt es trotzdem eine Möglichkeit die Größe des Arrays, also die>Anzahl der Elemente, in der Funktion "machwas" "herauszubekommen"?!?
Nur wenn die Arrays ein feste Länge haben, welche zur Compilezeit
bekannt ist.
MFG
Falk
Schlecht.
Im Moment kommt zwar 0x00 nicht als regulärer Wert vor, ich könnte ihn
also somit als "Flag" nehmen, aber ich muss es für spätere Anwendungen
"kompatibel" halten. Und da kann es sein, dass es 0x00 als Datenwert
vorkommt. ;(
Ich belasse es jetzt bei der Lösung. - Hab ich schon vorher mal
Testweise gehabt, fand ich aber keine schöne Lösung. Wenn's aber nicht
geht ....
Danke!
Gruß
Phil
Falk wrote:
> Nur wenn die Arrays ein feste Länge haben, welche zur Compilezeit> bekannt ist.
Die Größe eines Arrays ist dem Compiler immer zur Compilezeit
bekannt, sonst wäre es keins. Entweder hat sie der Programmierer
explizit festgelegt oder aber implizit, indem er [] schreibt und
die Gesamtgröße aus der Anzahl der Initialisierungselemente
genommen wird.
Etwas anderes ist es, wenn man malloc() benutzt, aber dann hat man
kein Array, sondern einen Zeiger.
@Jörg Wunsch
>Die Größe eines Arrays ist dem Compiler immer zur Compilezeit>bekannt, sonst wäre es keins. Entweder hat sie der Programmierer
Ähhhh, ja. ;-)
>Etwas anderes ist es, wenn man malloc() benutzt, aber dann hat man>kein Array, sondern einen Zeiger.
Das ist doch aber eben das Problem des OP, oder?
MFG
Falk
>Schlecht.>Im Moment kommt zwar 0x00 nicht als regulärer Wert vor, ich könnte ihn>also somit als "Flag" nehmen, aber ich muss es für spätere Anwendungen>"kompatibel" halten. Und da kann es sein, dass es 0x00 als Datenwert>vorkommt. ;(
Was ist genau "schlecht"?
Ich denke, Du vermischst Strings und Arrays. Wenn Du Deine Funktion so
aufbaust, wie Roland vorgeschlagen hat, hast Du keine Probleme mit der
"0" (solange Du nicht irgendwelche String-Funktionen auf Dein Array
loslässt):
1
machwas(uint8_t*pWerte,unint8_tsize){
2
...
3
}
Du kannst also auch Nullen in Dein Array füllen, die Größe, die Du mit
sizeof bestimmt hast, wird dadurch nicht tangiert.
Gruß, Stefan
Ok, jetzt versteh ich, was Jörg Wunsch mit "Du weißt, dass die Werte
zur Laufzeit zugewiesen werden, ja? Jedesmal beim Eintritt in die
Funktion." gemeint hat.
Wie gesagt, die größe ist dynamisch.
Falk wrote:
> @Phil>>>"machwas(werte, sizeof werte);">>Das ist ne gute Lösung! ;)>> Aber irgendwie glaube ich nciht, dass sie funktionieren wird.
In diesem speziellen Fall schon, da es sich um ein
uint8_t Array handelt.
Ansonsten macht man den Ansatz:
#define ELEMENTS(x) (sizeof(x)/sizeof(*x))
und benutzt
machwas( werte, ELEMENTS(werte) );
Man dividiert also die kokmplette Byte-Größe des
Arrays durch die Byte-Größe des ersten Elements
und erhält so die Anzahl der Elemente in diesem
Array.
Disclaimer: Das geht natürlich wieder nur, wenn ein
Array auch als Array sichtbar ist. In dem Moment, indem
ein Array zu einem Pointer degeneriert ist, klappt das
klarerweise nicht mehr.
Drum bin ich eigentlich auch ein Gegner der Schreibweise
void foo( int myArray[] )
{
}
denn das suggeriert etwas, das nicht stimmt: Da wird kein
Array übergeben, sondern die Adresse des ersten Elements.
Phil wrote:
> Ok, jetzt versteh ich, was Jörg Wunsch mit "Du weißt, dass die Werte> zur Laufzeit zugewiesen werden, ja? Jedesmal beim Eintritt in die> Funktion." gemeint hat.>> Wie gesagt, die größe ist dynamisch.>
> mache.>> Das muss doch irgendwie auch anders gehen, oder?
Nein.
Das geht nicht anders.
Das erste
1
uint8_twerte[]={0x12,0x33,0xA9,0x11,0xC8,0xE4};
ist keine Zuweisung, sondern einen Initialisierung.
Bei einer Initialisierung gelten andere Regeln.
Das hier
1
werte={0x12,0x33,0xA9,0x11,0xC8,0xE4};
wäre eine Zuweisung, so sie denn syntaktisch korrekt
wäre. Nur: In C kann man Arrays nicht zuweisen. Man
kann sie als ganzes initialisieren, aber man kann mit
einem Array als Ganzes praktisch nichts machen. Zb.
kann man einem Array nicht ein anderes Array zuweisen
und man kann daher auch ein Array nicht an eine Funktion
übergeben, denn dazu wäre ja die Zuweisung des
übergebenen Arrays an ein lokales Array innerhalb der
Funktion notwendig und das geht nicht (Array-Zuweisung).
Und wie dann?
Soll ich etwa jedesmal eine neue Variable als array anlegen?!?
Da kommt man ja irgendwann vor lauter Variablennamen völlig
durcheinander! ;(
Gruß
Phil
Falk wrote:
> @Jörg Wunsch>>>Du kannst sie in getrennten Blöcken anlegen:>>void bla(){>> ....>> {>> uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};>> ...>> machwas(werte);>> }>> ...>> {>> uint8_t werte[] = {0xFF, 0xC2, 0x1F, 0x88};>> ...>> machwas(werte);>> }>> ...>>}>> Werden dadurch nicht zwei Arrays angelegt? Speicherverbrauch?>
rein formal gesehen: ja.
Allerdings wird das erste Array zerstört, bevor das zweite
angelegt wird. Solange die Arrays gleich groß sind, stehen
die Chancen nicht schlecht, das beide Arrays im gleichen
Speicher erzeugt werden.
Ich würde allerdings für das Ganze wohl eher pgmspace-arrays
bevorzugen. Den Platz für die Initialisierungswerte braucht man
so und so im ROM (auf die eine oder andere Weise), und auf den
LPM- statt LDS-Zugriff kommt's sicher nicht an.
Seh ich auch so.
2 konstante globale Arrays ins Flash und falls die Funktionen
umschreiben zu aufwändig ist, bzw. die Werte zwischendurch
mal temporär geändert werden müssen, mittels memcpy_p ins
RAM holen.
(Dürfte aber für den OP noch zu schwierig sein :-)
Scheint mir auch so! ;) Überleg z.B. noch immer, für was "OP" stehen
soll.
Ich kann mir vorstellen, in welche Richtung es geht (=>
DAU/Newbie/Greenhorn) aber die richtigen Wörter hab ich noch nicht
gefunden. :D
Aber ich bin willig es zu lernen!
Gruß
Phil
Phil wrote:
> Scheint mir auch so! ;) Überleg z.B. noch immer, für was "OP" stehen> soll.
Sorry. Da kommt meine Vergangenheit in internationalen Foren durch.
OP steht für 'original Poster', also derjenige, der den Thread
eröffnet hat.
> Ich kann mir vorstellen, in welche Richtung es geht (=>> DAU/Newbie/Greenhorn) aber die richtigen Wörter hab ich noch nicht> gefunden. :D>> Aber ich bin willig es zu lernen!
Dann guckst du hier
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29