{0}
Co to znaczy, kiedy jest używany do inicjalizacji obiektu? {0}
Nigdzie nie mogę znaleźć żadnych odniesień , a ze względu na nawiasy klamrowe wyszukiwania w Google nie są pomocne.
Przykładowy kod:
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);
}
Bez tego powyższy kod ulegnie awarii podczas działania.
Należy pamiętać, że ta technika nie ustawi bajtów wypełniania na zero. Na przykład:
To nie to samo co:
W pierwszym przypadku bajty padu między c i i nie są inicjowane. Dlaczego miałbyś się przejmować? Cóż, jeśli zapisujesz te dane na dysku lub wysyłasz je przez sieć lub cokolwiek innego, możesz mieć problem z bezpieczeństwem.
źródło
Zauważ, że działa także pusty inicjator agregacji:
źródło
W odpowiedzi na
ShellExecuteEx()
to, dlaczego ulega awarii: TwojaSHELLEXECUTEINFO
struktura „sexi” ma wielu członków, a ty tylko inicjujesz niektóre z nich.Na przykład członek
sexi.lpDirectory
może wskazywać w dowolnym miejscu, aleShellExecuteEx()
nadal będzie próbował go użyć, dlatego wystąpi naruszenie zasad dostępu do pamięci.Po dodaniu wiersza:
przed resztą konfiguracji struktury mówisz kompilatorowi, aby wyzerował wszystkie elementy struktury, zanim zainicjujesz te, które Cię interesują.
ShellExecuteEx()
wie, że jeślisexi.lpDirectory
wynosi zero, powinno to zignorować.źródło
Używam go również do inicjowania ciągów znaków, np.
źródło
{0}
jest prawidłowym inicjatorem dla dowolnego typu (pełnego obiektu), zarówno w C, jak i C ++. Jest to powszechny idiom używany do inicjalizacji obiektu do zera (czytaj dalej, aby zobaczyć, co to oznacza).W przypadku typów skalarnych (typy arytmetyczne i wskaźniki) nawiasy klamrowe są niepotrzebne, ale są wyraźnie dozwolone. Cytując projekt normy N1570 normy ISO C, sekcja 6.7.9:
Inicjuje obiekt do zera (
0
dla liczb całkowitych,0.0
dla liczb zmiennoprzecinkowych, zerowy wskaźnik dla wskaźników).W przypadku typów innych niż skalarne (struktury, tablice, związki)
{0}
określa, że pierwszy element obiektu jest inicjowany na zero. W przypadku struktur zawierających struktury, tablice struktur itp. Stosuje się to rekurencyjnie, więc pierwszy element skalarny jest ustawiany na zero, odpowiednio do typu. Jak w każdym inicjalizatorze, wszelkie nieokreślone elementy są ustawiane na zero.Pośrednie nawiasy klamrowe (
{
,}
) można pominąć; na przykład oba są prawidłowe i równoważne:dlatego nie musisz na przykład pisać
{ { 0 } }
dla typu, którego pierwszym elementem jest nieskalarny.Więc to:
jest skrótowym sposobem inicjalizacji
obj
do zera, co oznacza, że każdy skalarny podobiektobj
jest ustawiony na,0
jeśli jest liczbą całkowitą,0.0
jeśli jest liczbą zmiennoprzecinkową, lub zerowym wskaźnikiem, jeśli jest wskaźnikiem.Zasady są podobne dla C ++.
W twoim konkretnym przypadku, ponieważ przypisujesz wartości do
sexi.cbSize
itd., JasneSHELLEXECUTEINFO
jest, że jest to struktura lub klasa (lub może związek, ale prawdopodobnie nie), więc nie wszystko to dotyczy, ale jak powiedziałem,{ 0 }
jest to powszechne idiom, którego można użyć w bardziej ogólnych sytuacjach.Nie jest to (koniecznie) równoważne z użyciem
memset
do ustawienia reprezentacji obiektu na zero-zero. Ani0.0
wskaźnik zmiennoprzecinkowy, ani wskaźnik zerowy nie są koniecznie reprezentowane jako zero-bitowe, a{ 0 }
inicjator niekoniecznie ustawia bajty wypełniające na jakąkolwiek konkretną wartość. Jednak w większości systemów może to mieć ten sam efekt.źródło
{0}
nie jest prawidłowym inicjatorem obiektu bez akceptacji konstruktora0
; ani dla agregatu, którego pierwszy element jest jako taki (lub agregatu bez elementów)Minęło trochę czasu, odkąd pracowałem w c / c ++, ale IIRC, ten sam skrót można również zastosować do tablic.
źródło
Zawsze zastanawiałem się, dlaczego powinieneś użyć czegoś takiego
Oto przypadek testowy do wyjaśnienia:
czek. c
Kompiluję z,
gcc -O2 -o check check.c
a następniereadelf -s check | sort -k 2
wypisuję tabelę symboli za pomocą (to jest z gcc 4.6.3 na Ubuntu 12.04.2 na systemie x64). Fragment:Ważną częścią jest to, że
my_zero_struct
później__bss_start
. Sekcja „.bss” w programie C to sekcja pamięci, która jest zerowana, zanimmain
zostanie nazwana patrz wikipedia na .bss .Jeśli zmienisz powyższy kod na:
Wynikowy plik wykonywalny „check” wygląda dokładnie tak samo, przynajmniej w kompilatorze gcc 4.6.3 na Ubuntu 12.04.2;
my_zero_struct
jest nadal w.bss
punkcie a tym samym zostanie on automatycznie inicjowany do zera, zanimmain
nazywa.Wskazówki w komentarzach, że a
memset
może zainicjować „pełną” strukturę, również nie stanowi ulepszenia, ponieważ.bss
sekcja jest całkowicie wyczyszczona, co oznacza również, że „pełna” struktura jest ustawiona na zero.Być może standard języka C nie wspomina o tym, ale w prawdziwym kompilatorze C nigdy nie widziałem innego zachowania.
źródło
To cukier syntetyczny, który inicjuje całą strukturę do wartości pustych / zerowych / zerowych.
Długa wersja
Krótka wersja
Czy to nie było o wiele łatwiejsze?
Jest to również miłe, ponieważ:
ZeroMemory
źródło
{0} jest anonimową tablicą zawierającą jej element jako 0.
Służy do inicjalizacji jednego lub wszystkich elementów tablicy z 0.
np. int arr [8] = {0};
W takim przypadku wszystkie elementy arr zostaną zainicjowane jako 0.
źródło
{0}
nie jest anonimową tablicą. To nawet nie jest wyrażenie. To inicjator.