2016-11-02 3 views
-1

Ich habe eine StrukturVerwendung von Literal-Arrays oder Verbindungen

typedef struct 
{ 
    int num_bytes; // number of relevant bytes 
    void * bytes_p; // pointer to bytes 
} BYTES_T; 

, die als Parameter an eine Vielzahl von Funktionen an vielen Orten übergeben wird.

Normalerweise verwende ich es wie folgt:

uint8_t my_array[] = {0x01, 0x03, 0xff} ; // example array 
BYTES_T my_bytes; 
my_bytes.bytes_p = my_array; 
my_bytes.num_bytes= sizeof(my_array); 

... 

foo(&my_bytes); // call a function 

Um Teile meines Codes zu machen lesbarer ich gleichzeitige Schaffung sowohl der Anordnung und der Struktur im selben Kontext vermeiden möchten.

So als ersten Versuch spielte ich mit einem Makro um, Verbindung Literale mit:

#define ARRAYINFO(A) &((BYTES_T){.bytes_p = ((A)), .num_bytes = sizeof(((A)))}) 

und verwenden Sie es wie

foo(ARRAYINFO(my_array)); 

Das funktioniert - wenn ein Array übergeben wird. Aber wenn ich die Zeiger auf ein Array übergeben, wird es - natürlich - produzieren Unsinn:

uint8_t * array_pointer = my_array; // this is allowed 
foo(ARRAYINFO(array_pointer));  // nonsense for num_bytes because sizeof() 

Daher ist dies gefährlich und nicht eine Option.

WEITERi dachte über ein Konstrukt, das die Struktur zu erstellen, ohne das Array erstellen explizit:

#define CREATE_BYTES(A) &((BYTES_T){.bytes_p = ((A)), .num_bytes = sizeof((A))}) 

BYTES_T my_bytes = CREATE_BYTES(((uint8_t []){1,2,3,4,5})); 

Dies scheint zu stehen, aber ich denke, dass das „interne“ Array, was die übergebenen wörtlichen zweimal im Speicher erzeugt wird (Das Makro wertet es zweimal aus).

Gibt es eine Lösung für eine solche Idee?

+3

Ehrlich gesagt, die Nicht-Makro-Version mehr lesbar ist. Ich schlage vor, Sie bleiben dabei. – 2501

Antwort

0

Dies scheint zu funktionieren, aber ich denke, dass die „interne“ Array, die wörtliche bestanden darstellt, die in Speicher zweimal erstellt wird (das Makro wertet es zweimal).

Vom C99 Standard:

6.5.3.4/2

sizeof Der Bediener die Größe (in Bytes) des Operanden liefert, der ein Ausdruck oder der geklammerten Name sein kann eines Typs. Die Größe wird aus dem Typ des Operanden bestimmt. Das Ergebnis ist eine ganze Zahl. Wenn der Typ des Operanden ein Arraytyp variabler Länge ist, wird der Operand ausgewertet; andernfalls wird der Operand nicht ausgewertet und das Ergebnis ist eine Integer-Konstante.

So wird A nur einmal in Ihrem Makro ausgewertet:

#define CREATE_BYTES(A) &((BYTES_T){.bytes_p = ((A)), .num_bytes = sizeof((A))}) 
+1

Es funktioniert. Aber trotzdem: Ich denke, dass die Verwendung eines solchen Makros zu gefährlich ist, da A auch ein Zeiger sein könnte, in welchem ​​Fall wir Unsinn für num_bytes bekommen. – michael

+0

Ich stimme zu, wir sollten diese Art von Konstruktionen in der realen Welt vermeiden. –

Verwandte Themen