mikrocontroller.net

Forum: Compiler & IDEs Schon wieder sizeof


Autor: Phil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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


Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
void machwas(uint8_t *werte, uint8_t count) {
  uint8_t i;
  for (i = 0; i < count; i++)
    ...werte[i]...
}

...
  machwas(werte, sizeof werte);

Autor: Roland Praml (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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));

Autor: Phil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"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"?!?

Autor: Roland Praml (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Stefan Kleinwort (_sk_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Phil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Stefan Kleinwort (_sk_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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):
machwas (uint8_t *pWerte, unint8_t size) {
 ...
}
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

Autor: Phil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
void bla(){
  ....
  uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};
  ...
  machwas(werte);
  ...
  werte[] = {0xFF, 0xC2, 0x1F, 0x88}; //geht nicht
  ...
  machwas(werte);
  ...
}

AVR will, dass ich die zweite Zuweisung so
werte[0] = 0xFF;
werte[1] = 0xC2;
werte[2] = 0x1F;
werte[3] = 0x88;
mache.

Das muss doch irgendwie auch anders gehen, oder?

Verzeiht, bin ein kleiner Newbie!

Danke schonmal!

Gruß
Phil

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
>
void bla(){
>   ....
>   uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};
>   ...
>   machwas(werte);
>   ...
>   werte[] = {0xFF, 0xC2, 0x1F, 0x88}; //geht nicht
>   ...
>   machwas(werte);
>   ...
> }
>
> AVR will, dass ich die zweite Zuweisung so
>
werte[0] = 0xFF;
> werte[1] = 0xC2;
> werte[2] = 0x1F;
> werte[3] = 0x88;
> 
> mache.
>
> Das muss doch irgendwie auch anders gehen, oder?

Nein.
Das geht nicht anders.

Das erste
  uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};

ist keine Zuweisung, sondern einen Initialisierung.
Bei einer Initialisierung gelten andere Regeln.

Das hier
  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).

Autor: Phil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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);
  }
  ...
}

Damit endet der Gültigkeitsbereich ("scope") eines jeden Arrays namens
"werte" an der schließenden geschweiften Klammer.

Autor: Phil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funtkioniert! - Danke!

Gruß
Phil

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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?

MfG
Falk

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 :-)

Autor: Phil (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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-Tu...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.