Ich möchte ein konstantes statisches Array erstellen, das in meiner gesamten Objective-C-Implementierungsdatei verwendet werden soll, ähnlich wie hier auf der obersten Ebene meiner “.m”-Datei:
static const int NUM_TYPES = 4;
static int types[NUM_TYPES] = {
1,
2,
3,
4 };
Ich plane die Verwendung NUM_TYPES später in der Datei, also wollte ich es in eine Variable einfügen.
Wenn ich dies mache, bekomme ich jedoch den Fehler
“Variable modifizierte ‘Typen’ im Dateibereich”
Ich nehme an, dass dies etwas damit zu tun haben könnte, dass die Array-Größe eine Variable ist (ich bekomme diese Meldung nicht, wenn ich dort ein Integer-Literal einfüge, wie z static int types[4]).
Ich möchte das beheben, aber vielleicht gehe ich alles falsch an … Ich habe hier 2 Ziele:
Um ein Array zu haben, auf das in der gesamten Datei zugegriffen werden kann
Einkapseln NUM_TYPES in eine Variable, damit ich nicht das gleiche Literal an verschiedenen Stellen in meiner Datei verstreut habe
Was passiert, wenn Sie es stattdessen als Define tun? #define kNUM_TYPES 4 ?
– Jorge Israel Peña
11. November 2009 um 2:22 Uhr
Das funktioniert … aus irgendeinem Grund habe ich versucht, mich von der Verwendung des Präprozessors fernzuhalten, weil ich dachte, ich hätte mich daran erinnert, das irgendwo gelesen zu haben, aber ich habe nur etwas mehr recherchiert und konnte keinen guten Grund finden, ihn in diesem Fall nicht zu verwenden. Ich denke, es ist möglicherweise weniger wünschenswert, wenn ich Objekte im Präprozessor erstelle (wie z @"An NSString literal") Das einzige, was an Ihrem Code nicht stimmt, ist, dass das Semikolon nicht benötigt wird.
– Sam
11. November 2009 um 2:54 Uhr
Ah ja, danke für die Hinweise und froh, dass ich helfen konnte.
Ändern eines definierten Objekts const (z.B. durch Wegwerfen const von einem Zeiger und Speichern eines Wertes) ist undefiniertes Verhalten; Daher ist der Wert eines solchen Objekts eine Kompilierzeit- oder Laufzeitkonstante (abhängig von der Speicherdauer). Der Wert kann nicht in einem konstanten Ausdruck verwendet werden, nur weil der C-Standard dies nicht vorsieht. (Wegwerfen const und das Speichern eines Werts ist erlaubt, wenn das Zielobjekt ohne definiert ist const oder dynamisch zugewiesen; Zeichenfolgenliterale sind es nicht const darf aber nicht angeschrieben werden.)
– Jilles
28. Dezember 2012 um 21:22 Uhr
@jilles “könnte möglicherweise durch Maschinencode geändert werden” bedeutet nicht, dass der Autor dieser Antwort meinte “könnte möglicherweise durch C-Code geändert werden”. Darüber hinaus hat dies einen weiteren sehr guten Grund: Es kann sein extern Konstanten in verschiedenen TUs, deren Wert beim Kompilieren der aktuellen TU nicht bekannt ist.
– Benutzer529758
29. November 2013 um 20:11 Uhr
Eine Möglichkeit, diese Antwort zu verbessern, besteht darin, zu zeigen, wie dieses Problem behoben werden kann.
– Georg Stocker
16. Mai 2016 um 13:02 Uhr
Wenn Sie den Präprozessor trotzdem verwenden, wie in den anderen Antworten angegeben, können Sie den Compiler dazu bringen, den Wert von zu bestimmen NUM_TYPES automatisch:
Wow, das ist wirklich cool … Ich wusste nicht, dass das möglich ist. Ich gehe davon aus, dass die Kosten für diese Berechnung vernachlässigbar sind. Darf ich auch davon ausgehen, dass ein Compiler dies auf einen statischen Wert optimieren könnte?
– Sam
11. November 2009 um 3:56 Uhr
Ja, das Ergebnis von sizeof bei solchen Objekten ist eine Kompilierzeitkonstante.
– Café
11. November 2009 um 4:02 Uhr
#define NUM_TYPES 4
Es ist auch möglich, eine Aufzählung zu verwenden.
Wie bereits in anderen Antworten erklärt, const in C bedeutet lediglich, dass eine Variable schreibgeschützt ist. Es ist immer noch ein Laufzeitwert. Sie können jedoch eine verwenden enum als reelle Konstante in C:
Imho ist dies ein Fehler in vielen C-Compilern. Ich weiß genau, dass die Compiler, mit denen ich gearbeitet habe, keine “statische konstante” Variable an einer Adresse speichern, sondern die Verwendung im Code durch die Konstante ersetzen. Dies kann überprüft werden, da Sie dieselbe Prüfsumme für den produzierten Code erhalten, wenn Sie eine #define-Direktive des Präprozessors und eine statische konstante Variable verwenden.
In jedem Fall sollten Sie statische Konstantenvariablen anstelle von #defines verwenden, wann immer dies möglich ist, da die statische Konstante typsicher ist.
14198000cookie-checkVariabel modifiziertes Array im Dateibereichyes
Was passiert, wenn Sie es stattdessen als Define tun?
#define kNUM_TYPES 4
?– Jorge Israel Peña
11. November 2009 um 2:22 Uhr
Das funktioniert … aus irgendeinem Grund habe ich versucht, mich von der Verwendung des Präprozessors fernzuhalten, weil ich dachte, ich hätte mich daran erinnert, das irgendwo gelesen zu haben, aber ich habe nur etwas mehr recherchiert und konnte keinen guten Grund finden, ihn in diesem Fall nicht zu verwenden. Ich denke, es ist möglicherweise weniger wünschenswert, wenn ich Objekte im Präprozessor erstelle (wie z
@"An NSString literal"
) Das einzige, was an Ihrem Code nicht stimmt, ist, dass das Semikolon nicht benötigt wird.– Sam
11. November 2009 um 2:54 Uhr
Ah ja, danke für die Hinweise und froh, dass ich helfen konnte.
– Jorge Israel Peña
11. November 2009 um 3:42 Uhr