2014-04-22 10 views
9

Definiert den Typ x und ein Array X dieses Typs.C: Wie kann man sizeof (array)/sizeof (struct) für externe Arrays ermitteln?

x.h:

typedef struct _x {int p, q, r;} x; 
extern x X[]; 

separate Datei mit dem riesigen Hupen Array X zu halten.

x.c:

#include "x.h" 
x X[] = {/* lotsa stuff */}; 

Jetzt möchte ich X verwenden:

main.c:

#include "x.h" 

int main() 
{ 
    int i; 

    for (i = 0; i < sizeof(X)/sizeof(x); i++) /* error here */ 
     invert(X[i]); 

    return 0; 
} 

main.c nicht kompiliert; der Fehler ist:

error: invalid application of ‘sizeof’ to incomplete type ‘struct x[]’ 

Wie erhalte ich die Größe der X ohne es zu hartzucodieren?

+0

wenn x eine Struktur Sie haben in der Regel sizeof (struct x) –

+1

keine Notwendigkeit angeben Struktur zu verwenden, wenn Sie – cppguy

Antwort

13

In x.h add:

extern size_t x_count; 

In x.c add:

size_t x_count = sizeof(X)/sizeof(x); 

dann wird die Variable x_count in der Schleife verwenden.

Die Division muss in der Kompilierungseinheit erfolgen, die den Array-Initialisierer enthält, so dass sie die Größe des gesamten Arrays kennt.

+0

typedef Ich habe ein wenig mehr Erklärung, warum dies sollte funktionieren. – Barmar

+3

Dies kann das spezifische Problem von OP lösen, aber im Allgemeinen ist es mangelhaft, da "count" immer noch kein konstanter Ausdruck ist und nicht überall verwendet werden kann, wo Sie 'sizeof' verwenden würden. Außerdem ist "int" der falsche Typ. Es sollte "size_t" sein. –

+0

Es ist so nah wie möglich mit separat kompilierten Modulen. Die Größe kann nur ein konstanter Ausdruck sein, wenn sich die Array-Initialisierung in derselben Kompilierungseinheit befindet. – Barmar

0

Sie können das nicht tun. Aber Sie können eine Möglichkeit bereitstellen, um die Größe zu erhalten.

Neben

extern x X[]; 

extern size_t xArraySize; 

oder bevorzugt hinzufügen,

extern size_t xArraySize(void); 

in x.h

es definieren in x.c.

Ihre Schleife ändern:

for (i = 0; i < xArraySize(); i++) 
    invert(X[i]); 
0

Wenn Sie einfach x.h einschließen, hat der Compiler keine Ahnung, wie groß X tatsächlich ist. Nur durch Betrachten von x.h gibt es keine Möglichkeit zu erraten. Sie haben X mit einer Größe zu erklären:

extern x X[15]; 
+1

Der ganze Sinn der Verwendung von 'sizeof (X)/sizeof (x)' ist, dass Sie die Anzahl der Elemente nicht fest codieren müssen Die Größe richtet sich automatisch nach der Anzahl der Elemente im Array-Initialisierer. – Barmar

3

Wenn es möglich ist, am Ende des Arrays einen Abschlussindikatoren zu stellen, wie zum Beispiel:

x X[] = {/* lotsa stuff */, NULL}; 

Es könnte sein, dass die Anzahl der Elemente in dem Array wären irrelevant:

#include "x.h" 

int main() 
    { 
    x *ptr = X; 

    while(ptr) 
     invert(ptr++); 

    return 0; 
    } 

Wenn die Anzahl der Elemente in dem Array benötigt wird, kann das obige Verfahren auch die Elemente zu zählen, verwendet werden werden.

3

Hier ist eine Lösung mit Verbindung Literale:

in .h

typedef struct _x {int p, q, r} x; 

#define LOTSA_STUFF  {1, 2, 3}, {4, 5, 7} 
#define LOTSA_STUFF_SIZE sizeof ((x[]) {LOTSA_STUFF}) 

extern x X[LOTSA_STUFF_SIZE]; 

und in .c

x X[LOTSA_STUFF_SIZE] = {LOTSA_STUFF}; 

Für die Definition in .c, können Sie noch besser machen und eine statische assert verwenden (Definition des STATIC_ASSERT ist als Übung für den Leser;):

x X[] = {LOTSA_STUFF}; 

STATIC_ASSERT(sizeof X != LOTSA_STUFF_SIZE, "oops, sizes are not equal"); 
+0

Was für ein cooles Beispiel. Ich habe niemals zusammengesetzte Literale verwendet und war mit der Syntax nicht vertraut. Es gibt einen wirklich guten Artikel über [Dr. Dobb's (http://www.drdobbs.com/the-new-c-compound-literals/184401404) für Leute, die daran interessiert sind, mehr zu lernen. –

+0

Oh ... und du verpasst ein "F" auf deiner 'LOTSA_STUF' in der vierten Zeile des' .h' Beispiels. –

+0

Diese Version erfordert immer noch, dass die Anfangsdaten in der Kopfzeile sichtbar sind, was ich meiner Meinung nach vermeiden wollte. –