La dimensione dell'array C ++ in base al parametro della funzione provoca errori di compilazione

StackOverflow https://stackoverflow.com/questions/312116

Domanda

Ho una semplice funzione in cui un array viene dichiarato con dimensioni a seconda del parametro che è int.

    void f(int n){
        char a[n];
    };

    int main() {
        return 0;
    }

Questo pezzo di codice si compila bene su GNU C ++ , ma non su MSVC del 2005.

Ottengo i seguenti errori di compilazione:

    .\main.cpp(4) : error C2057: expected constant expression
    .\main.cpp(4) : error C2466: cannot allocate an array of constant size 0
    .\main.cpp(4) : error C2133: 'a' : unknown size

Cosa posso fare per correggere questo?

(Sono interessato a far funzionare questo con MSVC, senza usare new / delete)

È stato utile?

Soluzione

Quello che hai trovato è una delle estensioni del compilatore Gnu al linguaggio C ++. In questo caso, Visual C ++ è completamente corretto. Le matrici in C ++ devono essere definite con una dimensione che è un'espressione costante in fase di compilazione.

C'era una funzione aggiunta a C nell'aggiornamento del 1999 a quella lingua chiamata array a lunghezza variabile, dove questo è legale. Se riesci a trovare un compilatore C che supporta C99, il che non è facile. Ma questa funzione non fa parte del C ++ standard, non verrà aggiunta nel prossimo aggiornamento allo standard C ++.

Esistono due soluzioni in C ++. Il primo è usare uno std :: vector, il secondo è solo usare l'operatore new []:

char *a = new char [n];

Mentre stavo scrivendo la mia risposta, un altro ha pubblicato un suggerimento per usare _alloca. Lo sconsiglio vivamente. Dovresti semplicemente scambiare un metodo non standard e non portatile con un altro come specifico del compilatore.

Altri suggerimenti

Il tuo metodo di allocazione dallo stack è un'estensione g ++. Per fare l'equivalente in MSVC, devi usare _alloca:

char *a = (char *)_alloca(n);

Stai usando qualcosa che non è uno standard. In realtà è C standard ma non C ++. È strano!

Spiegando un po 'di più, gli array stack di dimensioni di runtime non fanno parte di C ++, ma fanno parte di C99, l'ultimo standard per C. Questo & # 180; s perché alcuni compilatori lo ottengono, mentre altri no . Consiglierei di non usarlo, per evitare problemi di compatibilità del compilatore.

L'implementazione alternativa della funzionalità userebbe new ed delete, come pubblicato da strager.

È possibile utilizzare new / delete per allocare / liberare memoria sull'heap. Questo è più lento e probabilmente più soggetto a errori rispetto all'utilizzo di char [n], ma purtroppo non fa parte dello standard C ++.

È possibile utilizzare la classe di array con ambito boost per un metodo sicuro per le eccezioni per l'utilizzo di new []. delete [] viene automaticamente chiamato su a quando esce dal campo di applicazione.

void f(int n) {
    boost::scoped_array<char> a(new char[n]);

    /* Code here. */
}

Puoi anche usare std :: vector e riservare () alcuni byte:

void f(int n) {
    std::vector<char> a;
    a.resize(n);

    /* Code here. */
}

Se si si desidera utilizzare char [n], compilare come codice C99 anziché codice C ++.

Se per qualche motivo devi assolutamente allocare dati nello stack, usa _alloca o _malloca / _freea, che sono estensioni fornite dalle librerie MSVC e simili.

L'array a lunghezza variabile

è stato introdotto in C99. È supportato in gcc ma non in msvc. Secondo una persona del team di MSVC, Microsoft non ha in programma di supportare questa funzionalità nel proprio compilatore c / C ++. Ha suggerito di usare std :: vector in questi casi.

Si noti che C99 non richiede che l'array sia allocato nello stack. Il compilatore può allocarlo sull'heap. Tuttavia, gcc alloca l'array nello stack.

Tipicamente in C (eccetto i compilatori C99 come altri hanno sottolineato) e C ++, se si desidera allocare memoria nello stack, la dimensione di ciò che si desidera allocare deve essere conosciuta al momento della compilazione. Le variabili locali sono allocate nello stack, quindi un array la cui lunghezza dipende da un parametro di funzione in fase di esecuzione viola questa regola. Klein ha ragione a sottolineare che l'utilizzo del "nuovo" operatore è un modo per risolvere questo problema:


char *a = new char [n];

'a' è ancora una variabile locale allocata nello stack, ma invece di essere l'intero array (che ha una lunghezza variabile), è solo un puntatore a un array (che ha sempre le stesse dimensioni, e quindi noto al momento della compilazione tempo). L'array è allocato sull'heap, che in genere riproduce la controparte dello stack: lo stack è per cose con una dimensione nota al momento della compilazione e l'heap è per cose con una dimensione non nota al momento della compilazione.

Sarebbe ragionevole usare un vector<> anziché un array? Oppure, poiché stai sostituendo un char *, un std::string? Funzionano bene con le dimensioni di runtime, anche se potrebbero esserci altri motivi per non usarle.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top