Quando {0}
é usado para inicializar um objeto, o que isso significa? Não consigo encontrar referências a {0}
nenhum lugar e, por causa das chaves, as pesquisas no Google não são úteis.
Código de exemplo:
SHELLEXECUTEINFO sexi = {0}; // what does this do?
sexi.cbSize = sizeof(SHELLEXECUTEINFO);
sexi.hwnd = NULL;
sexi.fMask = SEE_MASK_NOCLOSEPROCESS;
sexi.lpFile = lpFile.c_str();
sexi.lpParameters = args;
sexi.nShow = nShow;
if(ShellExecuteEx(&sexi))
{
DWORD wait = WaitForSingleObject(sexi.hProcess, INFINITE);
if(wait == WAIT_OBJECT_0)
GetExitCodeProcess(sexi.hProcess, &returnCode);
}
Sem ele, o código acima falhará no tempo de execução.
Uma coisa a ter em atenção é que essa técnica não definirá bytes de preenchimento como zero. Por exemplo:
Não é o mesmo que:
No primeiro caso, os bytes do pad entre c e i não são inicializados. Por que você se importaria? Bem, se você estiver salvando esses dados em disco ou enviando-os por uma rede ou qualquer outra coisa, poderá ter um problema de segurança.
fonte
Observe que um inicializador agregado vazio também funciona:
fonte
Em resposta ao porquê
ShellExecuteEx()
está falhando: suaSHELLEXECUTEINFO
estrutura "sexi" tem muitos membros e você está inicializando apenas alguns deles.Por exemplo, o membro
sexi.lpDirectory
pode estar apontando para qualquer lugar, masShellExecuteEx()
ainda tentará usá-lo; portanto, você terá uma violação de acesso à memória.Quando você inclui a linha:
antes do resto da configuração da sua estrutura, você está dizendo ao compilador para zerar todos os membros da estrutura antes de inicializar os membros específicos em que você está interessado.
ShellExecuteEx()
sabe que sesexi.lpDirectory
for zero, deve ignorá-lo.fonte
Eu também o uso para inicializar strings, por exemplo.
fonte
{0}
é um inicializador válido para qualquer tipo (objeto completo), em C e C ++. É um idioma comum usado para inicializar um objeto para zero (leia para ver o que isso significa).Para tipos escalares (tipos aritmético e ponteiro), as chaves são desnecessárias, mas são explicitamente permitidas. Citando o rascunho N1570 da norma ISO C, seção 6.7.9:
Inicializa o objeto para zero (
0
para números inteiros,0.0
para ponto flutuante, um ponteiro nulo para ponteiros).Para tipos não escalares (estruturas, matrizes, uniões),
{0}
especifica que o primeiro elemento do objeto é inicializado como zero. Para estruturas que contêm estruturas, matrizes de estruturas e assim por diante, isso é aplicado recursivamente, para que o primeiro elemento escalar seja definido como zero, conforme apropriado para o tipo. Como em qualquer inicializador, qualquer elemento não especificado é definido como zero.Chaves intermediárias (
{
,}
) podem ser omitidas; por exemplo, ambos são válidos e equivalentes:é por isso que você não precisa escrever, por exemplo,
{ { 0 } }
para um tipo cujo primeiro elemento não seja escalar.Então, é isso:
é uma maneira abreviada de inicializar
obj
para zero, o que significa que cada subobjeto escalar deobj
é definido como0
se for um número inteiro,0.0
se for um ponto flutuante ou um ponteiro nulo, se for um ponteiro.As regras são semelhantes para C ++.
No seu caso particular, como você está atribuindo valores para
sexi.cbSize
e assim por diante, fica claro queSHELLEXECUTEINFO
é um tipo de estrutura ou classe (ou possivelmente uma união, mas provavelmente não), então nem tudo isso se aplica, mas, como eu disse,{ 0 }
é comum idioma que pode ser usado em situações mais gerais.Isso não é (necessariamente) equivalente a usar
memset
para definir a representação do objeto como all-bits-zero. Nem o ponto flutuante0.0
nem o ponteiro nulo são necessariamente representados como zero de todos os bits, e um{ 0 }
inicializador não define necessariamente bytes de preenchimento para nenhum valor específico. Na maioria dos sistemas, porém, é provável que tenha o mesmo efeito.fonte
{0}
não é um inicializador válido para um objeto sem aceitação do construtor0
; nem para um agregado cujo primeiro elemento é como tal (ou um agregado sem elementos)Já faz um tempo desde que eu trabalhei em c / c ++, mas no IIRC, o mesmo atalho também pode ser usado para matrizes.
fonte
Eu sempre me perguntei por que você deveria usar algo como
Aqui está um caso de teste para explicar:
check.c
Eu compilo com
gcc -O2 -o check check.c
e depoisreadelf -s check | sort -k 2
saio da tabela de símbolos (isto é com o gcc 4.6.3 no ubuntu 12.04.2 em um sistema x64). Excerto:A parte importante aqui é que
my_zero_struct
é depois__bss_start
. A seção ".bss" em um programa C é a seção da memória que é definida como zero antes demain
ser chamada, consulte a wikipedia em .bss .Se você alterar o código acima para:
Em seguida, o executável "check" resultante parece exatamente o mesmo pelo menos com o compilador gcc 4.6.3 no ubuntu 12.04.2; o
my_zero_struct
ainda está na.bss
seção e, portanto, será automaticamente inicializado como zero, antes demain
ser chamado.Dicas nos comentários, de que um
memset
pode inicializar a estrutura "completa" também não é uma melhoria, porque a.bss
seção é totalmente limpa, o que também significa que a estrutura "completa" está definida como zero.Ele pode ser que o padrão de linguagem C não menciona nada disso, mas em um compilador mundo real C Eu nunca vi um comportamento diferente.
fonte
É açúcar sintático inicializar toda a sua estrutura para valores vazios / zero / nulo.
Versão longa
Versão curta
Não foi muito mais fácil?
Também é legal porque:
ZeroMemory
fonte
{0} é uma matriz anônima que contém seu elemento como 0.
Isso é usado para inicializar um ou todos os elementos da matriz com 0.
por exemplo, int arr [8] = {0};
Nesse caso, todos os elementos de arr serão inicializados como 0.
fonte
{0}
não é uma matriz anônima. Nem sequer é uma expressão. É um inicializador.