Apenas curioso, o que realmente acontece se eu definir uma matriz de comprimento zero int array[0];
no código? O GCC não reclama de forma alguma.
Programa de amostra
#include <stdio.h>
int main() {
int arr[0];
return 0;
}
Esclarecimento
Na verdade, estou tentando descobrir se matrizes de comprimento zero inicializadas dessa maneira, em vez de serem apontadas como o comprimento variável nos comentários de Darhazer, são otimizadas ou não.
Isso ocorre porque eu tenho que liberar algum código para a natureza, então estou tentando descobrir se devo lidar com casos em que o SIZE
é definido como 0
, o que acontece em algum código com um estaticamente definidoint array[SIZE];
Fiquei realmente surpreso que o GCC não reclame, o que levou à minha pergunta. Das respostas que recebi, acredito que a falta de um aviso se deve em grande parte ao suporte ao código antigo que não foi atualizado com a nova sintaxe [].
Como eu estava pensando principalmente no erro, estou rotulando a resposta de Lundin como correta (a de Nawaz foi a primeira, mas não tão completa) - os outros estavam apontando seu uso real para estruturas acolchoadas, embora relevantes, não são ' exatamente o que eu estava procurando.
[]
em Python ou mesmo""
em C? Às vezes, você tem uma função ou macro que requer uma matriz, mas não possui dados para inserir nela.Respostas:
Uma matriz não pode ter tamanho zero.
ISO 9899: 2011 6.7.6.2:
O texto acima é verdadeiro tanto para uma matriz simples (parágrafo 1). Para um VLA (array de comprimento variável), o comportamento é indefinido se o valor da expressão for menor ou igual a zero (parágrafo 5). Este é um texto normativo no padrão C. Um compilador não tem permissão para implementá-lo de maneira diferente.
gcc -std=c99 -pedantic
emite um aviso para o caso não-VLA.fonte
#error
diretiva.#error
diretiva de pré - processador.Conforme o padrão, não é permitido.
No entanto, é prática corrente nos compiladores C tratar essas declarações como uma declaração de membro de matriz flexível ( FAM ) :
A sintaxe padrão de uma FAM é:
A ideia é que você o aloque assim:
Você também pode usá-lo estaticamente (extensão gcc):
Isso também é conhecido como estruturas acolchoadas (este termo é anterior à publicação do C99 Standard) ou struct hack (obrigado Joe Wreschnig por apontá-lo).
No entanto, essa sintaxe foi padronizada (e os efeitos garantidos) apenas recentemente em C99. Antes era necessário um tamanho constante.
1
era o caminho portátil a seguir, embora fosse bastante estranho.0
foi melhor em indicar intenção, mas não é legal no que diz respeito ao Padrão e foi suportado como uma extensão por alguns compiladores (incluindo o gcc).A prática de preenchimento da cauda, no entanto, depende do fato de que o armazenamento está disponível (cuidado
malloc
), portanto, não é adequado para empilhar o uso em geral.fonte
int content[];
aqui até onde eu entendi. Já que eu não sou muito experiente nos termos C da arte ... você poderia confirmar se meu raciocínio parece correto?foo[x]
com facilidade e utilidade parafoo[0]
sempre que houvessefoo
uma matriz de elemento único.No padrão C e C ++, a matriz de tamanho zero não é permitida.
Se você estiver usando o GCC, compile-o com a
-pedantic
opção Dará aviso , dizendo:No caso de C ++, ele fornece um aviso semelhante.
fonte
error C2466: cannot allocate an array of constant size 0
[BCC32 Error] test.c(3): E2021 Array must have at least one element
-pedantic -Werror
, você também pode fazer apenas #-pedantic-errors
std::array
. (Aparte: Lembro-me, mas não consegue encontrar a fonte que VLAs foram consideradas e explicitamente rejeitada de estar em C ++.)É totalmente ilegal, e sempre foi, mas muitos compiladores negligenciam o sinal do erro. Não sei por que você quer fazer isso. O único uso que eu sei é acionar um erro de tempo de compilação de um booleano:
Se
condition
é um falso, então eu recebo um erro de tempo de compilação. Como os compiladores permitem isso, no entanto, passei a usar:Isso fornece um tamanho de 1 ou -1, e eu nunca encontrei um compilador que aceitasse um tamanho de -1.
fonte
STATIC_ASSERT
usassem.#if condition \n #error whatever \n #endif
Acrescentarei que há uma página inteira da documentação on-line do gcc sobre esse argumento.
Algumas citações:
e
então você poderia
e boom :-)
fonte
int a[0]
, entãoa[0] = 1
a[1] = 2
?a[100000] = 5
mas se tiver sorte, simplesmente travará seu aplicativo, se tiver sorte: -)Outro uso de matrizes de comprimento zero é para criar objetos de comprimento variável (pré-C99). Matrizes de comprimento zero são diferentes das matrizes flexíveis que têm [] sem 0.
Citado no documento gcc :
Um exemplo do mundo real são matrizes de comprimento zero
struct kdbus_item
no kdbus.h (um módulo do kernel do Linux).fonte
void*
para fins aritméticos (portanto, é proibido adicionar ou subtrair ponteiros a objetos de tamanho zero). Embora os membros de matriz flexível sejam na maioria melhores do que matrizes de tamanho zero, eles também podem atuar como uma espécie de "união" para coisas de alias, sem adicionar um nível extra de indireto "sintático" ao que se segue (por exemplo, dado questruct foo {unsigned char as_bytes[0]; int x,y; float z;}
é possível acessar membrosx
..z
...myStruct.asFoo.x
, por exemplo , etc. Além disso, o IIRC, C grita com qualquer esforço para incluir um membro flexível da matriz dentro de uma estrutura, tornando impossível ter uma estrutura que inclua vários outros membros da matriz flexível de comprimento conhecido conteúdo.sizeof x->contents
é um erro no ISO C, em vez de retornar 0 no gcc. Matrizes de tamanho zero que não são membros de estrutura apresentam muitos outros problemas.struct {int n; THING dat[];}
e possa trabalhar com itens de duração estática ou automática.Declarações de matriz de tamanho zero dentro de estruturas seriam úteis se fossem permitidas e se a semântica fosse tal que (1) forçasse o alinhamento, mas não alocasse espaço, e (2) indexasse a matriz seria considerado um comportamento definido no caso em que o ponteiro resultante estaria dentro do mesmo bloco de memória que a estrutura. Esse comportamento nunca foi permitido por nenhum padrão C, mas alguns compiladores antigos o permitiram antes que se tornasse padrão para os compiladores permitirem declarações de matriz incompletas com colchetes vazios.
O truque de estrutura, como geralmente implementado usando uma matriz de tamanho 1, é desonesto e não acho que exista nenhum requisito de que os compiladores evitem quebrá-lo. Por exemplo, seria de esperar que se um compilador vê
int a[1]
, seria no seu direito de respeitoa[i]
comoa[0]
. Se alguém tentar solucionar os problemas de alinhamento do struct hack através de algo comoum compilador pode ficar esperto e assumir que o tamanho da matriz é realmente quatro:
Essa otimização pode ser razoável, especialmente se
myStruct->data
puder ser carregada em um registro na mesma operação quemyStruct->size
. Não sei nada no padrão que proíba essa otimização, embora, é claro, quebre qualquer código que possa esperar acessar coisas além do quarto elemento.fonte