C, C++: Vetores de tamanho zero

Um recurso bastante útil do GCC (apenas) são vetores de tamanho zero. O uso é permitido apenas como último elemento de uma estrutura de dados.

struct pessoa {
    int idade;
    char nome[0];
};
printf("%d\n", sizeof(struct pessoa)); // Imprime "4"

Note que a estrutura tem o mesmo tamanho de um inteiro (na minha máquina). Então podemos concluir que o vetor de tamanho zero não ocupa espaço, ele apenas serve como um identificador para a primeira posição de memória após a estrutura. Isto nos permite fazer algo assim:

struct pessoa * cria_pessoa(int idade, char* nome)
{
    int tamanho = sizeof(struct pessoa) + strlen(nome) + 1;
    struct pessoa *novo = malloc(tamanho);

    novo->idade = idade;
    strcpy(novo->nome, nome);

    return novo;
}
int main(void)
{
    struct pessoa *teste = cria_pessoa(18, "Jose");

    /* Imprime "Jose tem 18 anos." */
    printf("%s tem %d anos.\n", teste->nome, teste->idade);

    free(teste);

    return 0;
}

Note que conseguimos alocar toda a memória para a estrutura em apenas uma operação, o que não seria possível caso “nome” fosse um ponteiro, o que nos custaria mais uma chamada de malloc. Da mesma forma a desalocação de toda a estrutura foi feita usando um comando.

Esta técnica permite maior flexibilidade e um melhor aproveitamento de memória do que construir a estrutura com o atributo nome sendo “char nome[200]” (tamanho fixo) supondo que um nome nunca seria maior que 200 caracteres.

This entry was posted in C, CPP and tagged , , , , , , . Bookmark the permalink.

7 Responses to C, C++: Vetores de tamanho zero

  1. Douglas says:

    Funciona por causa do compilador.

    struct pessoa * cria_pessoa(int idade, char* nome)
    {

    strcpy(novo->nome, nome); /* aqui deveria dar segfault */

    }

    Compilando no gcc 4.0.1 no macbook sem usar flags, passa. Mas com -pedantic gera warning:
    vet0.c:7: warning: ISO C forbids zero-size array ‘nome’

  2. Douglas says:

    Oooopss… my bad

  3. zpu k says:

    C99 suporta “flexible arrays”. Referência: http://publib.boulder.ibm.com/infocenter/comphelp/v9v111/index.jsp?topic=/com.ibm.xlcpp9.aix.doc/language_ref/strct.htm

    Ver ali “Flexible array members” e “Zero-extent array members”. Especificamente:
    “””…
    Zero-extent array members

    A zero-extent array is an array with no dimensions. Like a flexible array member, a zero-extent array can be used to access a variable-length object. Unlike a flexible array member, a zero-extent array is not a C99 feature, but is provided for GNU C compatibility.
    …”””

    ;]

  4. Murilo Adriano says:

    Pra mim essa é nova…
    Gostei da idéia!
    Vou testar algumas coisinhas!

  5. Coster says:

    Se não me engano, o Codewarrior suporta isso também. Uma forma portável de fazer isso é declarando o array no fim da struct como tendo um elemento.

    Supondo que a struct seja do tipo S, e o array do tipo T (e o queremos com n elementos), é só alocar usando malloc(sizeof(S) + (n – 1) * sizeof(T))

  6. Adam says:

    Boa dica! e a do zpu k também!

Leave a Reply

Your email address will not be published. Required fields are marked *