Deserialisierung von Arrays
-
Ich kommuniziere gerade mit Smart Buttons und erhalte durch einen Socket die Packetdaten in einer Byte-Folge. Das Info Paket aus dem entsprechenden SDK sieht folgendermaßen aus:
typedef struct { uint8_t opcode; // Zur Unterscheidung der Paketdaten // ... uint8_t current_pending_connections; uint8_t currently_no_space_for_new_connection; uint16_t nb_verified_buttons; uint8_t bd_addr_of_verified_buttons[0][6]; } EvtGetInfoResponse; // 1 Byte aligned
Nicht zu unrecht motzt hier der Compiler über das [0][6] Array. Die Arraygröße ist hierbei abhängig von
nb_verified_buttons
Das Problem ist hierbei folgendes. Eigentlich könnte man ja
uint8_t bd_addr_of_verified_buttons[N][6];
setzen. Aber dann würde sich die Größe des Structs ändern. Und diese nehme ich zur Überprüfung der eingehenden Daten. Ich überprüfe erstens ob der Opcode stimmt und zweitens ob die Anzahl der empfangenen Daten größer gleichsizeof(EvtGetInfoResponse)
ist. Ist dies der Fall so lege ich einen EvtGetInfoResponse Zeiger auf die empfangenen Daten.Wie würdet ihr das sauber lösen ohne die Warnung zu ignorieren?
-
Kann denn der Fall
nb_verified_buttons = 0
vorkommen?
Ansonsten kannst du jauint8_t bd_addr_of_verified_buttons[1][6]
benutzen (also mindestens immer ein weiterer Datensatz).Welchen Compiler verwendest du denn? Seit C99 gibt es Flexible Array Member und einige C++ Compiler unterstützen dies auch, also
uint8_t bd_addr_of_verified_buttons[][6]
.
-
@Th69 sagte in Deserialisierung von Arrays:
Kann denn der Fall nb_verified_buttons = 0 vorkommen?
Leider ja
Welchen Compiler verwendest du denn?
Visual C++ 2019 (v142)
VLAs mag der C++ Compiler nicht. Mal schauen was der C Compiler sagt.
-
Hast du denn die MS-Extensions aktiviert? s.a. Arrays (C++): Stack declarations:
A zero-sized array is legal only when the array is the last field in a
struct
orunion
and when the Microsoft extensions are enabled (/Za or /permissive- isn't set).
-
@Th69 sagte in Deserialisierung von Arrays:
Hast du denn die MS-Extensions aktiviert?
Ich habe die Optionen eingestellt, aber trotzdem kommt die Warnung C4200.
Nutze ich VLA innerhalb einer C Datei, so funktioniert dies auch nicht. Es ist zum Mäuse melken...
Ich glaube das beste ist aktuell das Struct in zwei Kopien aufzusplitten.
In dem ersten Struct, nennen wir es
EvtGetInfoResponse0
, kommentiere ich die Zeileuint8_t bd_addr_of_verified_buttons[0][6];
aus.Im dem zweiten Struct setze ich die Arraygröße auf 1 und überprüfe nur rudimentär die Anzahl der empfangenen Bytes. Die benötigten Bytes dürfte dann mindestens
sizeof(EvtGetInfoResponse) + nb_verified_buttons * 6
seinUnd über die Falle Zeiger = 2D Array möchte ich nicht mehr stolpern.
BTW manuelle Speicherreservierung dürfte halt wg. dem 1 Byte Aligment kompliziert sein.
-
Du könntest ja folgendes zum Unterdrücken der Warnung verwenden
#pragma warning( push ) #pragma warning( disable : 4200 ) // ... #pragma warning( pop )
Laut warning pragma müßte auch einfach nur folgendes gehen:
#pragma warning( suppress: 4200 ) // ...
-
@Quiche-Lorraine sagte in Deserialisierung von Arrays:
Wie würdet ihr das sauber lösen ohne die Warnung zu ignorieren?
Eine weitere Lösung wäre, das Paket in dem Fall als zwei separate Typen zu interpretieren. Einmal als
struct
ohnebd_addr_of_verified_buttons
und fallsnb_verified_buttons => 1
gilt, liegt dahinter eben noch ein Array variabler Länge, mit dessen Adresse man z.B. einenuint8_t (*nb_verified_buttons)[6]
initialisieren könnte (Pointer auf ein Array mituint8_t[6]
-Elementen), um darauf zuzugreifen. Länge dieses Arrays ist dannresponse.nb_verified_buttons
.
-
#include <stdint.h> typedef struct { uint8_t opcode; // Zur Unterscheidung der Paketdaten // ... uint8_t current_pending_connections; uint8_t currently_no_space_for_new_connection; uint16_t nb_verified_buttons; uint8_t bd_addr_of_verified_buttons[1][6]; } EvtGetInfoResponse; static unsigned const EvtGetInfoResponseBaseSize = sizeof(EvtGetInfoResponse) - sizeof(((EvtGetInfoResponse*)0)->bd_addr_of_verified_buttons);
-
Danke für die vielen Tipps!
Ich habe dies jetzt in zwei seperaten Typen unterteilt und damit funktioniert es.