Arrays de tamanho zero

No último post usei um array de tamanho zero para exemplificar que um array pode, desde a especificação C99, ser “dinâmico”. O exemplo que dei foi esse:

struct String {
  int length;
  int ref_count;
  char data[0];
};

Se você obtiver o tamanho da estrutura String via sizeof, obterá 8 — Este é o tamanho dos dois inteiros na estrutura. O membro ‘data’ não tem tamanho.  O ponteiro ‘data’ aponta para o próximo byte após o membro ‘ref_count’, mas não deve ser usado sem que a estrutura seja propriamente alocada, caso contrário você corre o risco de obter um segmentation fault ou um buffer overrun, como no post anterior.

Eis a maneira correta de usar a estrutura acima:

struct String *str;
str = (struct String *)malloc(sizeof(struct String) + data_length);

/* As linhas abaixo são só para exemplificar o uso da estrutura
   no contexto da string em pascal. */
str->length = data_length;
str->ref_count = 1;

Onde data_length é o tamanho do array data que você quer usar. Note que se nossa estrutura fosse:

struct String {
  int length;
  int ref_count;
  char *data;
}

Embora isso “faça mais sentido”, é completamente diferente da definição original. O tamanho da estrutura é de 12 bytes (dois int‘s e um ponteiro) e o buffer apontado por data teria que ser alocado também. Na definição original o buffer data está contido na estrutura. Sacaram?

Se você usa o gcc, essa extensão está disponível desde a versão 3 do compilador (lembre-se que estou usando a versão 4.4 aqui).

Anúncios

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s