Variabel modifiziertes Array im Dateibereich

Lesezeit: 4 Minuten

Sams Benutzeravatar
Sam

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:

  1. Um ein Array zu haben, auf das in der gesamten Datei zugegriffen werden kann
  2. Einkapseln NUM_TYPES in eine Variable, damit ich nicht das gleiche Literal an verschiedenen Stellen in meiner Datei verstreut habe

Irgendwelche Vorschläge?

[EDIT]

Gefunden in der C-Faq: http://c-faq.com/ansi/constasconst.html

  • 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

Benutzeravatar von larsr
Larsr

Der Grund für diese Warnung ist folgender const in c bedeutet nicht konstant. Es bedeutet „schreibgeschützt“. Der Wert wird also an einer Speicheradresse gespeichert und könnte möglicherweise durch Maschinencode geändert werden.

  • Ä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:

#define NUM_TYPES (sizeof types / sizeof types[0])
static int types[] = { 
  1,
  2, 
  3, 
  4 };

  • 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.

typedef enum {
    typeNo1 = 1,
    typeNo2,
    typeNo3,
    typeNo4,
    NumOfTypes = typeNo4
}  TypeOfSomething;

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:

enum { NUM_TYPES = 4 };
static int types[NUM_TYPES] = { 
  1, 2, 3, 4
};

Benutzeravatar von hans lepoeter
Hans Lepoeter

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.

1419800cookie-checkVariabel modifiziertes Array im Dateibereich

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy