Por que o tamanho global da matriz deve ser uma constante inteira?

8

Em C ++, tentei declarar uma matriz global de algum tamanho. Eu recebi o erro:

O limite da matriz não é uma constante inteira antes do token ']'

Mas quando declarei uma matriz do mesmo tipo na main()função, ela está funcionando bem.

Por que existe um comportamento diferente aqui?

int y=5;
int arr[y];         //When I comment this line it works fine

int main()
{
    int x=5;
    int arr2[x];        // This line doesn't show any error.
}

Edit: Muitos estão sugerindo que esta pergunta é uma duplicata do Obtendo o erro "array bound não é uma constante inteira antes do símbolo ']'" . Mas essa pergunta não responde por que há um comportamento diferente.

Syed Maqthyar
fonte
3
Mesmo mainnão sendo legal, ele usa a extensão VLA.
Jarod42 10/03
4
Os limites de todas as matrizes, em C ++, precisam ter um valor conhecido durante a compilação. Se esse código, quando inserido, mainfor "aceito" pelo seu compilador: você está usando a extensão do compilador, que permite que os VLAs sejam compilados, mesmo que não sejam suportados pelo padrão C ++.
Algirdas Preidžius
2
não confunda "sem erros de compilação" com "está funcionando bem". Nesse caso, "funcionando bem" significa que seu código depende de uma extensão fornecida pelo compilador não padrão, ou seja, está ok, mas não é portátil c ++
idclev 463035818
Por que não declarar ye xcomo const? Você precisa modificar o valor de you x? Espero que não, porque isso levanta muitas questões sobre o tamanho arre arr2deve ser - principalmente no que diz respeito à ordem de inicialização. (Dica: eles devem ser constantes)
Wyck
Compile seu programa com --std=c++17(ou --std=c++11se for um compilador antigo) e a compilação falhará.
einpoklum 10/03

Respostas:

9

Ambos os exemplos estão mal formados em C ++. Se um compilador não diagnosticar o último, ele não estará em conformidade com o padrão.

Por que existe um comportamento diferente aqui?

Você usa uma extensão de idioma que permite matrizes automáticas com duração de tempo de execução. Mas não permite matrizes estáticas de comprimento de tempo de execução. Matrizes globais têm armazenamento estático.

Caso você esteja usando o GCC, você pode solicitar que ele esteja em conformidade com o padrão usando a opção de linha de comando -pedantic. É uma boa idéia fazê-lo para ser informado sobre os problemas de portabilidade.

eerorika
fonte
4

O tamanho de uma matriz deve ser uma constante. Você pode corrigir isso declarando ycomo const.

const int y=5;
int arr[y]; 

Quanto ao motivo pelo qual isso funcionou main, o g ++ permite uma matriz de comprimento variável no escopo do bloco como uma extensão. No entanto, não é C ++ padrão.

dbush
fonte
0

Ambos não devem ser usados, funciona: porque (como @eerorika disse) matrizes automáticas de comprimento são permitidas em tempo de execução, mas as matrizes globais precisam ter armazenamento estático.

Se você deseja declarar uma matriz com um tamanho variável (por exemplo, dado por std :: cin), faria algo como:

int x;
std::cin >> x;
const int n = x;
float arr[n];

Mas você não seria capaz de configurá-lo para conter apenas zeros com float arr[n] = {0}(se você precisar adicionar um valor na matriz, sem ter certeza de defini-lo), seria necessário usar um loop como esse

for(int i = 0; i < n; i++)
{
    arr[i] = 0;
}
Jacob Korba
fonte
1
Seu exemplo ainda está mal formado, apesar de usar const. O tamanho deve ser uma expressão constante de tempo de compilação. Algo que você obtém da entrada em tempo de execução, é claro, não satisfaz isso.
eerorika 10/03
A afirmação de que "ambos não devem ser usados" é inadequada. Pode-se evitar o uso de uma matriz de comprimento variável para escrever código C ++ portátil. Pode-se desejar usar uma matriz de comprimento variável para atingir uma meta de projeto desejada às custas da portabilidade. Os valores desses objetivos são subjetivos e circunstanciais, e você não pode dizer onde está o equilíbrio para outra pessoa.
Eric Postpischil 10/03
@EricPostpischil Você está certo, mas quando você usa uma variável mutável, pode alterá-la e, por razões de segurança, é melhor mantê-la como uma const
Jacob Korba
0

O sistema de tipos do C ++ lida com essas matrizes do tipo C da maneira que define arr2 no seu exemplo de tipo int[5]. Portanto, sim, o número de elementos da matriz faz parte do tipo!

Isso coloca algumas restrições no que você tem permissão para usar na definição de matrizes do tipo C. Ou seja, esse número precisa ter armazenamento estático , precisa ser imutável e precisa estar disponível em tempo de compilação .

Portanto, convém alterar seu código para algo como o seguinte, que terá outro benefício. Inicializa a matriz de maneira adequada:

int arr2[] = {0, 0, 0, 0, 0};   
salchint
fonte