Wenn {0}
verwendet wird , um ein Objekt zu initialisieren, was bedeutet es? Ich kann {0}
nirgendwo Verweise finden und wegen der geschweiften Klammern ist die Google-Suche nicht hilfreich.
Beispielcode:
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);
}
Ohne diesen Absturz stürzt der obige Code zur Laufzeit ab.
Eine Sache, die Sie beachten sollten, ist, dass diese Technik die Füllbytes nicht auf Null setzt. Beispielsweise:
Ist nicht dasselbe wie:
Im ersten Fall werden Pad-Bytes zwischen c und i nicht initialisiert. Warum sollte es dich interessieren? Wenn Sie diese Daten auf der Festplatte speichern oder über ein Netzwerk oder was auch immer senden, liegt möglicherweise ein Sicherheitsproblem vor.
quelle
Beachten Sie, dass ein leerer Aggregatinitialisierer auch funktioniert:
quelle
Als Antwort darauf, warum
ShellExecuteEx()
es abstürzt: IhreSHELLEXECUTEINFO
"sexi" -Struktur hat viele Mitglieder und Sie initialisieren nur einige von ihnen.Das Mitglied
sexi.lpDirectory
könnte beispielsweise auf eine beliebige Stelle zeigen, versucht jedochShellExecuteEx()
weiterhin, sie zu verwenden, sodass eine Speicherzugriffsverletzung auftritt.Wenn Sie die Zeile einfügen:
Vor dem Rest Ihrer Struktureinrichtung weisen Sie den Compiler an, alle Strukturelemente auf Null zu setzen, bevor Sie die spezifischen Elemente initialisieren, an denen Sie interessiert sind.
ShellExecuteEx()
Wennsexi.lpDirectory
Null ist, sollte er diese ignorieren.quelle
Ich benutze es auch, um Strings zu initialisieren, z.
quelle
{0}
ist ein gültiger Initialisierer für jeden (vollständigen Objekt-) Typ in C und C ++. Es ist eine gebräuchliche Redewendung, mit der ein Objekt auf Null initialisiert wird (lesen Sie weiter, um zu sehen, was das bedeutet).Für Skalartypen (Arithmetik- und Zeigertypen) sind die geschweiften Klammern nicht erforderlich, aber ausdrücklich zulässig. Zitieren des N1570-Entwurfs der ISO C-Norm, Abschnitt 6.7.9:
Es initialisiert das Objekt auf Null (
0
für Ganzzahlen,0.0
für Gleitkomma, einen Nullzeiger für Zeiger).Gibt für nicht skalare Typen (Strukturen, Arrays, Vereinigungen) an,
{0}
dass das erste Element des Objekts auf Null initialisiert wird. Bei Strukturen, die Strukturen, Arrays von Strukturen usw. enthalten, wird dies rekursiv angewendet, sodass das erste Skalarelement je nach Typ auf Null gesetzt wird. Wie bei jedem Initialisierer werden alle nicht angegebenen Elemente auf Null gesetzt.Zwischenklammern (
{
,}
) können weggelassen werden; Zum Beispiel sind beide gültig und gleichwertig:Deshalb müssen Sie beispielsweise nicht
{ { 0 } }
für einen Typ schreiben, dessen erstes Element nicht skalar ist.Also das:
ist eine Kurzform der Initialisierung
obj
auf Null, was bedeutet, dass jedes skalare Unterobjekt von aufobj
gesetzt wird,0
wenn es eine Ganzzahl ist,0.0
wenn es Gleitkomma ist, oder auf einen Nullzeiger, wenn es ein Zeiger ist.Die Regeln für C ++ sind ähnlich.
In Ihrem speziellen Fall ist
sexi.cbSize
es klar, dassSHELLEXECUTEINFO
es sich um einen Struktur- oder Klassentyp handelt (oder möglicherweise um eine Vereinigung, aber wahrscheinlich nicht) , da Sie Werte usw. zuweisen. Dies gilt also nicht für alles, aber wie gesagt,{ 0 }
ist es üblich Redewendung, die in allgemeineren Situationen verwendet werden kann.Dies ist nicht (notwendigerweise) gleichbedeutend mit der Verwendung
memset
, um die Darstellung des Objekts auf alle Bits Null zu setzen. Weder Gleitkomma0.0
noch ein Nullzeiger werden notwendigerweise als All-Bit-Null dargestellt, und ein{ 0 }
Initialisierer setzt nicht notwendigerweise Füllbytes auf einen bestimmten Wert. Auf den meisten Systemen hat dies jedoch wahrscheinlich den gleichen Effekt.quelle
{0}
kein gültiger Initialisierer für ein Objekt, das kein Konstruktor akzeptiert0
. noch für ein Aggregat, dessen erstes Element als solches ist (oder ein Aggregat ohne Elemente)Es ist schon eine Weile her, dass ich in c / c ++ gearbeitet habe, aber IIRC, dieselbe Verknüpfung kann auch für Arrays verwendet werden.
quelle
Ich habe mich immer gefragt, warum Sie so etwas verwenden sollten
Hier ist ein Testfall zu erklären:
check.c
Ich kompiliere mit
gcc -O2 -o check check.c
undreadelf -s check | sort -k 2
gebe dann die Symboltabelle mit aus (dies ist mit gcc 4.6.3 unter Ubuntu 12.04.2 auf einem x64-System). Auszug:Der wichtige Teil hier ist, das
my_zero_struct
ist danach__bss_start
. Der Abschnitt ".bss" in einem C-Programm ist der Speicherabschnitt, der auf Null gesetzt wurde, bevor ermain
aufgerufen wird (siehe Wikipedia auf .bss) .Wenn Sie den obigen Code ändern in:
Dann wird die resultierende „check“ ausführbare sieht genau die gleiche zumindest mit den gcc 4.6.3 Compiler auf Ubuntu 12.04.2; Das
my_zero_struct
befindet sich noch im.bss
Abschnitt und wird daher automatisch auf Null initialisiert, bevormain
es aufgerufen wird.Hinweise in den Kommentaren, dass a
memset
möglicherweise die "vollständige" Struktur initialisiert, sind ebenfalls keine Verbesserung, da der.bss
Abschnitt vollständig gelöscht wird, was auch bedeutet, dass die "vollständige" Struktur auf Null gesetzt ist.Es kann sein, dass der C-Sprachstandard nichts davon erwähnt, aber in einem realen C-Compiler habe ich noch nie ein anderes Verhalten gesehen.
quelle
Es ist syntatischer Zucker, um Ihre gesamte Struktur auf leere / Null / Null-Werte zu initialisieren.
Lange Version
Kurzfassung
War das nicht viel einfacher?
Es ist auch schön, weil:
ZeroMemory
quelle
{0} ist ein anonymes Array , dessen Element 0 ist.
Dies wird verwendet, um ein oder alle Elemente des Arrays mit 0 zu initialisieren.
zB int arr [8] = {0};
In diesem Fall werden alle Elemente von arr als 0 initialisiert.
quelle
{0}
ist kein anonymes Array. Es ist nicht einmal ein Ausdruck. Es ist ein Initialisierer.