Schon wieder sizeof

Gast #531629
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

Moderator Persönliche Seite #531635
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.
1
void machwas(uint8_t *werte, uint8_t count) {
2
  uint8_t i;
3
  for (i = 0; i < count; i++)
4
    ...werte[i]...
5
}
6

7
...
8
  machwas(werte, sizeof werte);
Gast #531638
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));
Gast #531640
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"?!?
Gast #531653
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)
Moderator Persönliche Seite #531657
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?
#531659
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
Gast #531662
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
Gast #531664
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
Moderator Persönliche Seite #531671
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.
Gast #531684
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
#531702
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):
1
machwas (uint8_t *pWerte, unint8_t size) {
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
Gast #531729
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.
1
void bla(){
2
  ....
3
  uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};
4
  ...
5
  machwas(werte);
6
  ...
7
  werte[] = {0xFF, 0xC2, 0x1F, 0x88}; //geht nicht
8
  ...
9
  machwas(werte);
10
  ...
11
}

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

Das muss doch irgendwie auch anders gehen, oder?

Verzeiht, bin ein kleiner Newbie!

Danke schonmal!

Gruß
Phil
#531731
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.
#531740
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.
>
1
void bla(){
2
>   ....
3
>   uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};
4
>   ...
5
>   machwas(werte);
6
>   ...
7
>   werte[] = {0xFF, 0xC2, 0x1F, 0x88}; //geht nicht
8
>   ...
9
>   machwas(werte);
10
>   ...
11
> }
>
> AVR will, dass ich die zweite Zuweisung so
>
1
werte[0] = 0xFF;
2
> werte[1] = 0xC2;
3
> werte[2] = 0x1F;
4
> werte[3] = 0x88;
5
>
> mache.
>
> Das muss doch irgendwie auch anders gehen, oder?

Nein.
Das geht nicht anders.

Das erste
1
  uint8_t werte[] = {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).
Moderator Persönliche Seite #531752
Lesenswert?

Du kannst sie in getrennten Blöcken anlegen:
1
void bla(){
2
  ....
3
  {
4
    uint8_t werte[] = {0x12, 0x33, 0xA9, 0x11, 0xC8, 0xE4};
5
    ...
6
    machwas(werte);
7
  }
8
  ...
9
  {
10
    uint8_t werte[] = {0xFF, 0xC2, 0x1F, 0x88};
11
    ...
12
    machwas(werte);
13
  }
14
  ...
15
}

Damit endet der Gültigkeitsbereich ("scope") eines jeden Arrays namens
"werte" an der schließenden geschweiften Klammer.
Gast #532183
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
#532206
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.
Gast #532375
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
#532389
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-Tutorial#Programmspeicher_.28Flash.29

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren