Forum: Compiler & IDEs C pointer in Struct-Array übergeben


von RH (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem:

Ich möchte uint32_t integer Variablen in ein uint8_t Array schreiben. 
Die Variablen werden einem struct zugeordnet und bekommen dort einen 
Namen. Der Variablenwert wird als Zeiger auf die jeweilige Variable in 
der structur hinterlegt.

Das Füllen des uint8_t Arrays möchte ich nun über den in dem struct 
hinterlegten pointer machen (siehe Code).
1
struct uint32_t_variable
2
{
3
  char* name[10];
4
  uint32_t* ptr;
5
};
6
7
struct uint32_t_variable uint32_t_variablen[] =
8
{
9
    {"Zähler 1", &cnt},
10
    {"Zähler 2", &cnt2}
11
};
12
uint8_t nmbr_of_uint32_t_variables = sizeof(uint32_t_variablen)/sizeof(*uint32_t_variablen);

mit der Funktion void MP_update_array(void) möchte ich nun das Array 
tx_value_buffer updaten. wie folgt:
1
void MP_update_array(void){
2
  uint8_t *pos = tx_value_buffer;
3
  for(int i = 0; i < nmbr_of_uint32_t_variables; i++){
4
    uint32_t* value = uint32_t_variablen[i].ptr;
5
    *pos = *value >> 24;
6
    pos++;
7
    *pos = *value >> 16;
8
    pos++;
9
    *pos = *value >> 8;
10
    pos++;
11
    *pos = *value;
12
    pos++;
13
  }
14
}

Leider wird mir hier in das Array eine sehr hohe Zahl (vermutlich die 
Speicheradressen?) geschrieben. Wenn ich *pos = &cnt; anstelle von *pos 
= *value; schreibe wird mir der richtige Wert ins Array geschrieben. Das 
riecht stark nach einem Fehler in meinem struct aber was mache ich 
falsch? Ich verzweifle.

Das ganze läuft in der STM32CubeIDE auf einem STM32G0 Kern.

: Verschoben durch Moderator
von Jim M. (turboj)


Lesenswert?

STM32 ist little endian.

von z.B. (Gast)


Lesenswert?

RH schrieb:
> struct uint32_t_variable
> {
>   char* name[10];
>   uint32_t* ptr;
> };
>
> struct uint32_t_variable uint32_t_variablen[] =
> {
>     {"Zähler 1", &cnt},
>     {"Zähler 2", &cnt2}
> };

in der struct ist char* ein Array von Zeigern (und kein Stringarray - 
was die Zuweisung wohl annimmt).

von C++ ist doof (Gast)


Lesenswert?

in C
1
   uint32_t x = 0x10203040;
2
   printf("als int32-Wert: %#x\n", x);
3
4
   uint8_t* p = (uint8_t*)&x;
5
6
   uint8_t arr[4];
7
8
   for (int i = 0; i < 4; i++)
9
      arr[i] = *p++;
10
11
   uint32_t* p32 = (uint32_t*)arr;
12
13
   printf("als Array: %#x\n", *p32);

von Andreas J. (ajbln)


Lesenswert?

RH schrieb:
> uint32_t* value = uint32_t_variablen[i].ptr;
>     *pos = *value >> 24;
>     pos++;
>     *pos = *value >> 16;
>     pos++;
>     *pos = *value >> 8;
>     pos++;
>     *pos = *value;
>     pos++;

Stattdessen kannst Du auch folgendes machen:

    *reinterpret_cast<uint32_t*>(pos) = *value;
    pos += sizeof(uint32_t);

So bleibt die Endianess aber gleich! Wenn Du aber Little Endian bist und 
Big Endian rausschreiben willst wie in Deinem Code (Highbyte first), 
musst Du die Endianess vorher drehen.

Das geht z.B. so (kann aber von der Plattform abhängen):

    *reinterpret_cast<uint32_t*>(pos) = htobe32(*value);

Versuche nicht von Hand zu drehen, viele Prozessoren haben dafür 
spezielle Maschinenbefehle, daher sind solche Endianessconverter immer 
sinnvoller.
Wie gesagt, je nach Plattform können sie auch anders heißen.
Meistens irgendwas mit h(ost) to 32 bits oder unsigned integer...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.