Inicializando uma estrutura para 0

116

Se eu tiver uma estrutura como esta:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

Qual seria a maneira mais fácil de inicializar essa estrutura para 0? O seguinte seria suficiente?

myStruct _m1 = {0};

ou Eu precisaria iniciar explicitamente cada membro em 0?

myStruct _m2 = {0,0};
Daan Timmer
fonte

Respostas:

143

O primeiro é o mais fácil ( envolve menos digitação ) e é garantido que funcione, todos os membros serão configurados para 0[Ref 1] .
O segundo é mais legível.

A escolha depende da preferência do usuário ou daquela que seu padrão de codificação exige.

[Ref 1] Referência C99 Padrão 6.7.8.21:

Se houver menos inicializadores em uma lista entre chaves do que elementos ou membros de um agregado, ou menos caracteres em um literal de string usado para inicializar uma matriz de tamanho conhecido do que elementos na matriz, o restante do agregado deve ser inicializado implicitamente da mesma forma que os objetos que têm duração de armazenamento estático.

Boa leitura:
C e C ++: inicialização parcial da estrutura automática

Alok Save
fonte
9
Além disso, estou usando = {};No entanto, não tenho certeza se isso é válido.
William Entriken
15
@FullDecent colchetes vazios para inicialização é uma extensão GNU.
A3f
2
@ alias65536 A pergunta está marcada como C, não C ++.
A3f
3
Recebi um erro: "chaves ausentes ao redor do inicializador [-Werror = chaves ausentes]" provavelmente devido a uma matriz de membro: /
DrumM
3
@Edenia. Discordo. Eu já sei o que foo = {0}significa. Se eu visse foo = ZERO_FULL, teria que pesquisar a definição de ZERO_FULL.
Andrew Bainbridge
32

Se os dados forem uma variável estática ou global, eles são preenchidos com zero por padrão, então apenas declare-os myStruct _m;

Se os dados forem uma variável local ou uma zona alocada no heap, limpe-os com memset:

memset(&m, 0, sizeof(myStruct));

Os compiladores atuais (por exemplo, versões recentes de gcc) otimizam isso muito bem na prática. Isso funciona apenas se todos os valores zero (incluindo ponteiros nulos e zero de ponto flutuante) forem representados como todos os bits zero, o que é verdadeiro em todas as plataformas que conheço (mas o padrão C permite implementações onde isso é falso; não conheço essa implementação) .

Você poderia talvez codificar myStruct m = {};ou myStruct m = {0};(mesmo se o primeiro membro de myStructnão for um escalar).

Meu sentimento é que usar memsetpara estruturas locais é o melhor, e transmite melhor o fato de que em tempo de execução, algo deve ser feito (enquanto normalmente, dados globais e estáticos podem ser entendidos como inicializados em tempo de compilação, sem nenhum custo em tempo de execução) .

Basile Starynkevitch
fonte
7
Não há garantia de que definir todos os bytes da estrutura como 0será equivalente a inicializar todos os membros da estrutura com 0embora. Em muitas plataformas, isso será verdade, mas não universalmente.
Sander De Dycker
1
Você pode dar um exemplo, Sander? Curiosidade genuína. (Obviamente, não universalmente verdadeiro não significa necessariamente que haja uma exceção fácil de explicar, mas se houver ...)
Steven Fisher
2
O padrão C permite que o ponteiro nulo (ou um número de ponto flutuante zero) seja representado na memória por algo diferente de todos os bits zero. Muito poucas e estranhas implementações estão fazendo isso (não posso citar nenhum).
Basile Starynkevitch
-1, você pode achar a inicialização que o OP pergunta feia, mas é exatamente o que é previsto pelo padrão e que pode ser facilmente otimizado por todos os compiladores. Então, o formulário {}não é válido em C, mas está disponível apenas em C ++.
Jens Gustedt
7
@Steven: Só consigo pensar em plataformas obscuras e / ou antigas. O C FAQ tem uma lista de plataformas que tinham um NULLponteiro que nem todos eram 0bits: c-faq.com/null/machexamp.html . E então há a possibilidade de a plataforma não estar usando IEEE 754 para representar valores de ponto flutuante, mas usar alguma outra representação que não tenha um valor de todos os 0bits 0.0- mas admito que não conheço tal plataforma.
Sander De Dycker
19

Consulte §6.7.9 Inicialização:

21 Se houver menos inicializadores em uma lista entre chaves do que elementos ou membros de um agregado, ou menos caracteres em um literal de string usado para inicializar uma matriz de tamanho conhecido do que os elementos na matriz, o restante do agregado deve obrigatoriamente ser inicializado implicitamente da mesma forma que objetos que possuem duração de armazenamento estático.

Então, sim, ambos funcionam. Observe que no C99 uma nova forma de inicialização, chamada inicialização designada, também pode ser usada:

myStruct _m1 = {.c2 = 0, .c1 = 1};
diretamente
fonte
Mais notavelmente, já é C89: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Importante para alvos específicos de processamento de sinal)
Tobias