2008-11-23 11 views
17

Tengo una función simple en la que una matriz se declara con el tamaño dependiendo del parámetro que es int.El tamaño de la matriz C++ depende del parámetro de función provoca errores de compilación

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

    int main() { 
     return 0; 
    } 

Esta pieza de código compila bien en GNU C++, pero no en MSVC 2005.

me sale el siguiente error de compilación:

.\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 

¿Qué puedo hacer para corregir esto?

(Estoy interesado en hacer este trabajo con MSVC, sin necesidad de utilizar nuevos/delete)

Respuesta

29

Lo que has encontrado es una de las extensiones del compilador Gnu para el lenguaje C++. En este caso, Visual C++ es completamente correcto. Las matrices en C++ se deben definir con un tamaño que sea una expresión constante en tiempo de compilación.

Hubo una característica agregada a C en la actualización de 1999 a ese lenguaje llamada matrices de longitud variable, donde esto es legal. Si puede encontrar un compilador de C que sea compatible con C99, no es fácil. Pero esta característica no es parte de C++ estándar, no se agregará en la próxima actualización del estándar de C++.

Hay dos soluciones en C++. La primera es utilizar un std :: vector, el segundo es sólo para usar el operador new []:

char *a = new char [n]; 

Mientras estaba escribiendo mi respuesta, otro registró una sugerencia de utilizar _alloca. Recomiendo encarecidamente en contra de eso. Simplemente cambiaría un método no estándar y no portátil por otro igual que el compilador específico.

+1

Sí, pero asignar desde el montón, lo que "nuevo" hace, es muy diferente de asignar desde la pila, que es lo que el OP está tratando de hacer. (Podría tratarse de un código sensible al rendimiento que está intentando compilar). –

+0

No hay tantas preocupaciones sobre el rendimiento por el momento, pensé que era natural trabajar ... pero si no es parte del estándar de C++ entonces entiendo – xxxxxxx

+0

Re: _alloca: OP solo preguntó por obtener código equivalente trabajando en MSVC y sin usar new/delete. –

9

Su método de asignación de la pila es una extensión de g ++. Para hacer el equivalente bajo MSVC, es necesario utilizar _alloca:

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

¡Oh, eso se asigna a la pila! eso es maravilloso :) ¡Gracias! – xxxxxxx

+1

Tenga en cuenta este comentario de la página de manual de alloca: ERRORES La función alloca es dependiente de la máquina y el compilador. En muchos sistemas, su implementación tiene errores. Su uso es desaconsejado. –

+0

Sí, pero funciona bajo MSVC, que es con lo que OP intentaba hacer funcionar su código. Lo he estado usando por años. –

2

Puede utilizar nuevos/borrar para asignar/liberar memoria en el montón. Esto es más lento y posiblemente más propenso a errores que el uso de char [n], pero lamentablemente no forma parte del estándar C++.

Puede utilizar la clase de matriz con ámbito de boost para un método de excepción para usar el nuevo []. delete [] se llama automáticamente en a cuando sale del ámbito.

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

    /* Code here. */ 
} 

también puede utilizar std :: vector, y reserva() algunos bytes:

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

    /* Code here. */ 
} 

Si hace desee utilizar char [n], compila como código de C99 en lugar de C++ código.

Si por alguna razón tiene que asignar datos en la pila, use _alloca o _malloca/_freea, que son extensiones proporcionadas por MSVC libs y tal.

+0

sí, pero no entiendo por qué g ++ no tiene ningún problema con esto, mientras que MSVC falla – xxxxxxx

+0

Esto está mal ya que asigna del montón Él quiere asignar en la pila, que es lo que hace la versión de G ++. La razón por la que MSVC no compila la versión original es porque es una extensión de g ++. –

+0

No puede tenerlo en la pila con MSVC. Puede tenerlo en el montón, o tener un tamaño constante, no hay forma de asignar una matriz de tamaño variable en la pila con MSVC. –

5

Está utilizando algo que no es un estándar. En realidad es estándar C pero no C++. ¡Qué peculiar es eso!

Explicando un poco más, las matrices de pila de tamaño de ejecución no son parte de C++, pero son parte de C99, el último estándar para C.Es por eso que algunos compiladores lo obtendrán, mientras que otros no lo obtendrán. Recomiendo abstenerse de usarlo para evitar problemas de compatibilidad con el compilador.

La implementación alternativa de la funcionalidad sería usar new y delete, según lo publicado por strager.

+1

¡No es "peculiar" en absoluto ...! –

1

Normalmente en C (exceptuando los compiladores C99 como han señalado otros) y C++, si desea asignar memoria en la pila, debe conocerse el tamaño de lo que desea asignar en tiempo de compilación. Las variables locales se asignan en la pila, por lo que una matriz cuya longitud depende de un parámetro de función en tiempo de ejecución viola esta regla. Klein es correcta la afirmación de que el uso de la 'nueva' operador es una manera de resolver este problema:

 

char *a = new char [n]; 

'a' es todavía una variable local asignado a la pila, pero en lugar de toda la matriz (que tiene longitud variable), es solo un puntero a una matriz (que siempre tiene el mismo tamaño y, por lo tanto, se conoce en tiempo de compilación). La matriz se asigna en el montón, que generalmente juega la contraparte de la pila: la pila es para cosas con un tamaño conocido en tiempo de compilación, y el montón es para cosas con un tamaño desconocido en una época de compilación.

1

¿Sería razonable usar un vector<> en lugar de una matriz? O bien, dado que está reemplazando un char *, un std::string? Esos funcionan bien con el tamaño del tiempo de ejecución, aunque puede haber otras razones para no usarlos.

2

matriz de longitud variable se introdujo en C99. Es compatible con gcc pero no con msvc. De acuerdo con una persona en el equipo de MSVC, Microsoft no tiene ningún plan para admitir esta característica en su compilador c/C++. Sugirió usar std :: vector en esos casos.

Tenga en cuenta que C99 no requiere que la matriz asignada en la pila. El compilador puede asignarlo en el montón. Sin embargo, gcc asigna la matriz en la pila.

Cuestiones relacionadas