Go Down

Topic: Wo ist mein Denkfehler? sizeof(const uint8_t array[]) (Read 1 time) previous topic - next topic

LeRoi

Ich hab folgenden Code im Atmel Studio C Projekt (flashe auf Arduino UNO mit avrdude über Bootloader):

const uint8_t TEST[] = {5, 5, 5, 5, 5, 5, 30, 30};
uint8_t intervalCount;

intervalCount = sizeof(TEST); // das geht -> intervalCount = 8


Wie kann ich daraus eine Funktion machen? Die Arraygröße soll nicht defined werden.
So geht es jedenfalls nicht. Wo ist mein Denkfehler?

void setIntervalCount(const uint8_t timeIntervalArray[]) {
  intervalCount = sizeof(timeIntervalArray); // falsch -> intervalCount = 2, wohl nur die size vom Pointer, aber wie bekomm ich hier die Elementanzahl?
}

setIntervalCount(TEST); // != intervalCount = sizeof(TEST);

Serenifly

#1
Jun 02, 2016, 06:36 pm Last Edit: Jun 02, 2016, 07:07 pm by Serenifly
Array-Variablen zerfallen zu Zeigern. Ganz normal.

Es geht wenn du eine Referenz als Parameter verwendest und die Größe fest machst:
Code: [Select]

byte test[] = { 1, 2, 3 };
const int ARRAY_SIZE = sizeof(test) / sizeof(test[0]);

void func(byte (&arr)[ARRAY_SIZE])
{
   //sizeof() geht hier korrekt
}



Oder mit einer Template-Funktion:
Code: [Select]

template <typename T, int N>
void func(T (&arr)[N])
{
}


Dann muss die Größe nicht im Parameter fixiert sein. Das erzeugt aber für jede verschiedene Größe die man übergibt eine neue Funktion!

jurs

void setIntervalCount(const uint8_t timeIntervalArray[]) {
 intervalCount = sizeof(timeIntervalArray); // falsch -> intervalCount = 2, wohl nur die size vom Pointer, aber wie bekomm ich hier die Elementanzahl?
}

Wenn Du ein Arrray mit null Elementen deklarierst, und es nicht initialisierst, dann hat es null Elemente. Du hast quasi nur den Arrray-Pointer timeIntervalArray mit 2 Bytes (Pointergröße auf 8-Bit Atmegas) deklariert.

LeRoi

Danke für die Antworten. Ja, irgendwie etwas umständlich unschön alles. Hab mich eben zu lange mit Java beschäftigt. Mit Assembler wär es noch hässlicher mit den ganzen 'magic numbers', oder Vordefinitionen, die dann nötig werden. Jetzt fällt mir auch auf, warum man in vielen C Funktionen mit buffern oft die buffersize übergibt.
Mir ist noch ne Alternnative zu dem template eingefallen. Template kannte ich noch garnicht. Ich nehm jetztn Makro. Da kann ich mir das doppelte Angeben des gleichen arrays auch sparen.

#define FUNCTION(x) function(x, sizeof(x))

Eine zusätzliche Variable für die array size wollte ich verhindern. Wieder was Neues gelernt.

Eine Frage noch:
Warum nimmt man oft bei size of sizeof(test) / sizeof(test[0])? Bei einem byte array sollte doch sizeof(test) allein auch reichen? Jedenfalls liefert es den gleichen Wert. Bei größeren Elementen versteh ich es ja.

Serenifly

Warum nimmt man oft bei size of sizeof(test) / sizeof(test[0])?
Gewohnheit. Außerdem muss man dann nicht nachdenken ob es wirklich zum Datentyp passt. So kann man den Code auch leichter ändern.

LeRoi

Gewohnheit. Außerdem muss man dann nicht nachdenken ob es wirklich zum Datentyp passt. So kann man den Code auch leichter ändern.
Jo, da is was dran.

michael_x

Quote
void func(byte (&arr)[ARRAY_SIZE])
@Serenifly: Da hast du einen seltsamen Denkfehler, finde ich:
Warum übergibst du eine Arrayreferenz als Parameter, wenn du die Array-Größe nicht auch mit übergibst?
Als Parameter geht nur ein byte-Array mit 3 Elementen.
Ich meine, entweder arbeitet func immer mit dem globalen Array byte TEST[3], dann braucht auch keine referenz dazu als Parameter übergeben werden, oder func geht mit jedem byte Array, dann muss ihm aber auch die Größe mit übergeben werden.

sizeof innerhalb der Funktion, um dies variabel zu halten, funktioniert so jedenfalls nicht wirklich, denke ich.
sizeof ist keine Funktion, die zur Laufzeit einen Wert ermittelt.

Serenifly

Der "Fehler" ist ein anderer: es geht schon mit verschiedenen Arrays. Aber nur wenn die alle die gleiche Größe haben. Dann könnte man natürlich auch gleich auf ARRAY_SIZE direkt zugreifen, statt nochmal sizeof() zu machen.
sizeof() geht in diesem Fall weil die Größe im Parameter steckt.


Wenn man mehrere Arrays unterschiedlicher Größe als Argument will, kann man wie gesagt ein Template draus machen. Das ist das gleiche Prinzip. Aber dann sollte die Funktion nicht allzu groß sein, sonst steigt der Flash verbrauch evtl. unangenehm stark.

michael_x

Richtig, aber einfacher wäre doch, wenn die Funktion verschiedene Array-Größen können soll, die Array-Größe auch als Parameter mitzugeben. Oder?
"sizeof ist keine Funktion, die zur Laufzeit ausgewertet wird!" ist meiner Meinug nach die Antwort auf die Frage "Wo ist mein Denkfehler?"

Serenifly

Klar. Das ist der klassische C Weg und damit ist man am flexibelsten. Dass er das kennt, hat er auch in #3 gesagt.

Ich bin von dem ursprünglichen Code davon ausgegangen, dass er Array und Größe eher in einem Parameter wollte. Das war wahrscheinlich falsch.

Go Up