2015-06-01 12 views
5

So möchte ich eine Definition der Größe eines Arrays in einer Struktur zur Kompilierzeit bekannt haben. Ich möchte auch, dass diese Nummer als Variable für die Benutzerfreundlichkeit später verfügbar ist. Was ich habe, ist folgendes:Strukturelement Array-Größe basierend auf Const Int über Dateien

const int BANANA_ARRAY_SIZE = 10; 

typedef struct 
{ 
    char bananas[BANANA_ARRAY_SIZE]; 
    int some_other_stuff; 
} banana_struct; 

Das funktioniert gut. Wenn ich es jedoch in einer .h-Datei habe, die an mehreren Stellen eingefügt wird, beschwert sich der Compiler über die Neudefinition von BANANA_ARRAY_SIZE (was Sinn macht). Also muss ich es als extern deklarieren, damit mehrere Kompilierungseinheiten davon erfahren können.

So, ich habe jetzt

extern const int BANANA_ARRAY_SIZE; 

typedef struct 
{ 
    //.. same as before 
} banana_struct; 

und in einer Implementierungsdatei Ich habe

const int BANANA_ARRAY_SIZE = 10; 

Aber jetzt ist der Compiler lässt mich nicht die Struktur definieren mehr mit Beschwerden von

fields must have a constant size: variable length array in structure 

Gibt es eine Möglichkeit, wie ich erreichen kann, was ich will (haben Länge des Arrays in Variable gespeichert und verwendet zu definieren Struktur)?

Edit:

Als Reaktion auf die Vorschläge statt #define s zu verwenden, würde ich eher nicht.

Meine Frage ist, wie dieser konstante Wert in einer Variablen gespeichert wird und auch verwendet, um die Länge eines Arrays in einer Struktur festzulegen. Wenn Sie eine weitere Rechtfertigung benötigen, nehmen Sie an, dass ich eine Funktion benötige, die einen Zeiger auf einen int-Wert anwendet. Kann nicht eine Referenz von #define nehmen.

+1

Sie können diese Art der Initialisierung natürlich nur im lokalen Bereich in C durchführen, nicht im globalen Bereich, den Sie versuchen. *** [ref] (http://stackoverflow.com/a/11541168/645128) *** und im selben Beitrag: *** [ref2] (http://stackoverflow.com/a/11542474/645128) *** – ryyker

+0

Bitte lesen Sie meinen aktualisierten Kommentar, den letzten Kommentar zu meiner Antwort. Es passiert nicht für mich _gcc-5.1.0_. –

+3

'#define BANANA_ARRAY_SIZE 10'' Char Bananen [BANANA_ARRAY_SIZE]; const size_t length = BANANA_ARRAY_SIZE; ' – chux

Antwort

7

In der C-Sprache verwenden const Objekt kein Konstante ist. Sie können damit kein Nicht-VLA-Array deklarieren. Ihre erste Deklaration ist nicht in C-Sprache kompilierbar, was es unklar macht, was Sie unter "funktioniert gut" verstehen.

Sehen Sie hier für weitere Informationen: Shall I prefer constants over defines?

In Ihrem Fall, dass Sie entweder #define oder enum Konstanten beschränkt sind. Wenn Sie auch Zeiger auf diesen Wert erstellen möchten, müssen Sie zusätzlich ein Objekt const mit dem gleichen Wert deklarieren, entweder global oder lokal. Aber Sie können es nicht in Nicht-VLA-Array-Deklarationen verwenden. Stattdessen müssen Sie die Konstante #define oder enum verwenden. Z.B.

+0

Ich frage mich, ob gcc ist nicht konform in Bezug auf diese, wie folgt: const int LEN = 12; char my_array [LEN]; int main() {mein_array [0] = 'a'; zurückgeben 0; } kompiliert gut ... Wie auch immer, ich denke, dass im Wesentlichen "das kann nicht nach Spezifikation erfolgen" in c. Danke für die Information! – Phildo

+0

@Phildo: '-std = c99' oder' c11'? Es ist nicht die "Spezifikation", sondern der Standard. – Olaf

+0

@Phildo: Das ist in keiner Version von C definitiv nicht kompatibel. Sind Sie sicher, dass Sie im C-Modus und nicht im C++ - Modus kompilieren? In C++ wäre das legal. – AnT

0

Sie müssen extern dafür verwenden, so es ist nicht neu definiert, und Sie werden es einmal in einer einzigen Datei .c definieren müssen.

Beispiel

  1. header.h

    extern const int BANANA_ARRAY_SIZE; 
    
  2. main.c

    void banana(void); /* provide a prototype for `banana()' */ 
    /* A single definition */ 
    const int BANANA_ARRAY_SIZE = 10; 
    
    int main(void) 
    { 
        banana(); 
        return 0; 
    } 
    

Dies ist zu Demonstrationszwecken, Sie fügen Sie nicht nur die Prototypen im realen Leben, müssen Sie über den Quellcode Layout kümmern und dafür sorgen, dass der Prototyp die Funktionsdefinition übereinstimmt, usw.

  1. banane.c

    #include "header.h" 
    #include <stdio.h> 
    
    void banana(void) 
    { 
        printf("%d\n", BANANA_ARRAY_SIZE); 
    } 
    

Kompilieren mit

gcc -Wall -Werror -o banana banana.c main.c  

wenn 10 druckt ausgeführt.

Aber ich würde ein Makro stattdessen wie

#define BANANA_ARRAY_SIZE 10 

dann empfehlen kann man sogar bei der Kompilierung definiert es wie

gcc -DBANANA_ARRAY_SIZE=10 a.c b.c d.c -o executable 

Neudefinition zu verhindern oder gar keine Definition in einem all gängigen Kopf Datei würde enthalten

#ifndef BANANA_ARRAY_SIZE 
#define BANANA_ARRAY_SIZE 10 
#endif 
+0

Wenn Sie versuchen, was? Es funktioniert für mich! –

+0

Wie ist das anders als was OP hat? Er explizit erwähnt, dass er 'extern' in der Header-Datei verwendet hat. Die Frage ist etwa ich definiere die Struktur in der Header - Datei, während ich die Definition 'BANANA_ARRAY_SIZE' in der .c –

+0

halte Ich weiß, dass ich extern benutze. Ich habe das sogar in meiner Frage. Die Frage ist: "Warum kann ich den externen const - Wert nicht verwenden Länge des Arrays? ". Siehe auch meine Bearbeitung re: mit #defines – Phildo

4

Sie können entweder einen Enum oder ein #define

enum { 
BANANA_ARRAY_SIZE = 10 
}; 

oder

#define BANANA_ARRAY_SIZE 10 
0

Gemäß C11 Entwurf 6.6 # 10, "Eine Implementierung kann andere Formen von konstanten Ausdrücken akzeptieren.".

versucht, dass mit gcc 4.8.2:

static const size_t arr_size = 10; // static does not change anything 
static int arr[arr_size];   // dito 

gcc -std=gnu11 -Wall test.c 

test.c:6:12: error: variably modified ‘arr’ at file scope 
static int arr[arr_size]; 

das funktioniert also nicht (ich habe surprized würde, wenn es hatte). Sogar wenn ID funktioniert, wäre es Implementierung definiert und könnte sogar zwischen zwei Patches für den gleichen Compiler ändern.

Es gibt einen klaren Grund dafür nicht funktioniert, expecially, wenn die const hat globale Reichweite: Wenn ein Modul kompiliert wird, die den Header mit der Deklaration enthält, hat der Compiler keine Möglichkeit, den tatsächlichen Wert diese knwo Konstante Variable (!).Also, wie würde es Platz für das Array in .bss Abschnitt reservieren oder in der Lage sein, für Bereiche zu überprüfen, wenn Initialisierungen gegeben sind (und alloc Speicherplatz im .data Abschnitt)? Das würde eine Intervention durch den Linker erfordern und hätte viel mehr Auswirkungen auf Initialisierer usw. Ich bin mir ziemlich sicher, dass kein Compiler dies aus den angegebenen Gründen akzeptieren wird.


So haben Sie #define zu verwenden greifen:

"array.h": 
#define MAX_ARR_LEN 10 
extern const size_t max_arr_len; 

"array.c": 
const size_t max_arr_len = 10; 

Hinweis: size_t für Feldgrenzen verwenden. Dafür ist es (unter anderem).

Verwandte Themen