2013-04-08 11 views
5

Secondo this answer, in cui si afferma:Perché le funzioni C++ possono creare matrici di lunghezze variabili?

Il compilatore conosce la dimensione del tipo int e quindi in grado di generare l'istruzione assembler giusto che riserverà uno spazio sufficiente sulla pila al fine di lasciare foo vivere lì.

un compilatore deve conoscere la dimensione che una funzione occuperà nello stack per implementarlo.

Quindi, perché questo codice viene compilato?

int f(int n) 
{ 
    int x[n]; 
} 

int main() 
{ 
    f(3); 
    f(5); 
    //etc 
} 

x è un array di interi, ma le sue dimensioni non è costante, può cambiare in qualsiasi momento la funzione viene richiamata.

Cosa mi manca qui?

+5

Compilalo di nuovo con '-pedantic'. – chris

+1

"erw.cpp: nella funzione 'int f (int)': erw.cpp: 3: 12: avviso: ISO C++ proibisce l'array di lunghezza variabile 'x' [-Wvla]" - @chris: grazie, questo ha senso adesso. – corazza

+0

possibile duplicato di [Nei libri C++, l'array associato deve essere un'espressione costante, ma perché funziona il seguente codice?] (Http://stackoverflow.com/questions/5947661/in-c-books-array-bound-must-be -constant-expression-but-why-the-following-cod) –

risposta

8

Questo non è un codice legale in Standard C++. Si compila grazie a un'estensione specifica per il tuo compilatore che supporta variable-length arrays, che è una funzionalità C99.

Ma ancora, questo è non C++ portatile. Se avete bisogno di dimensionamento dinamico, si potrebbe riscrivere la funzione in questo modo:

#include <vector> 

int f(int n) 
{ 
    std::vector<int> v(n); 
} 

In caso contrario, ne fanno un modello e scrivere in questo modo: lavoro

#include <array> 

template<std::size_t N> 
int f() 
{ 
    std::array<int, N> a; 
} 
4

Compila perché si sta utilizzando un'estensione non standard. In senso stretto, non è un C++ valido, ma alcuni compilatori lo supportano.

Nel tuo caso (3 e 5 sono noti), è possibile utilizzare modelli invece, che sarebbero validi, o direttamente uno std::vector.

template<int n> 
int f() 
{ 
    int x[n]; 
} 

//... 
f<3>(); 
0

del compilatore è davvero difficile in questo caso. Ora ha bisogno di emettere il codice che - al momento dell'esecuzione - capirà quanta memoria è necessaria (n*sizeof(int)), e da dove ottenere quella memoria. Quella memoria è ancora rilasciata nello stesso posto in cui sarebbe stato rilasciato int y[5];, quindi sotto questo aspetto non cambia nulla.

Una soluzione facile per il compilatore è la modifica del codice dietro le quinte a int * __x = malloc(n*sizeof(int) ... free(__x). Potrebbe anche essere necessario riscrivere un codice per sizeof(x), ma anche in questo caso il compilatore può riscrivere il codice VLA in codice "normale". Non c'è bisogno di magia; I VLA possono essere implementati come semplice zucchero sintattico.

Problemi correlati