Chcę utworzyć stałą tablicę statyczną, która będzie używana w całym moim pliku implementacji Objective-C, podobną do tego na najwyższym poziomie mojego pliku „.m”:
static const int NUM_TYPES = 4;
static int types[NUM_TYPES] = {
1,
2,
3,
4 };
Planuję użyć NUM_TYPES
później w pliku, więc chciałem umieścić go w zmiennej.
Jednak kiedy to robię, pojawia się błąd
„Zmienione„ typy ”w zakresie pliku”
Rozumiem, że może to mieć coś wspólnego z rozmiarem tablicy jako zmienną (nie dostaję tego komunikatu, gdy umieszczam tam literał liczby całkowitej static int types[4]
).
Chcę to naprawić, ale może wszystko źle robię ... Mam tutaj 2 cele:
- Posiadać tablicę, która jest dostępna w całym pliku
- Aby zamknąć
NUM_TYPES
w zmiennej, aby nie mieć tego samego literału rozproszonego w różnych miejscach w moim pliku
Jakieś sugestie?
[EDYTUJ] Znalezione w C Faq: http://c-faq.com/ansi/constasconst.html
#define kNUM_TYPES 4
?@"An NSString literal"
) Jedyną wadą twojego fragmentu kodu jest to, że nie ma potrzeby używania średnika.Odpowiedzi:
Powodem tego ostrzeżenia jest to, że const w c nie oznacza stałej. To znaczy „tylko do odczytu”. Zatem wartość jest przechowywana pod adresem pamięci i może zostać zmieniona przez kod maszynowy.
źródło
const
(na przykład przez odrzucenieconst
wskaźnika i zapisanie wartości) jest niezdefiniowanym zachowaniem; dlatego wartość takiego obiektu jest stałą czasu kompilacji lub czasu wykonywania (w zależności od czasu przechowywania). Wartość nie może być używana w wyrażeniu stałym tylko dlatego, że standard C nie mówi, że może być. (Odrzucanieconst
i przechowywanie wartości jest dozwolone, jeśli obiekt docelowy jest zdefiniowany bezconst
lub dynamicznie przydzielony; literały łańcuchowe nie są,const
ale nie mogą być zapisywane.)extern
stałe w różnych jednostkach tłumaczeniowych, których wartość nie jest znana podczas kompilowania bieżącej jednostki tłumaczeniowej.Jeśli i tak zamierzasz używać preprocesora, zgodnie z innymi odpowiedziami, możesz zmusić kompilator do określenia wartości
NUM_TYPES
automagicznie:#define NUM_TYPES (sizeof types / sizeof types[0]) static int types[] = { 1, 2, 3, 4 };
źródło
sizeof
on obiektów jest stała czasu kompilacji.#define NUM_TYPES 4
źródło
Możliwe jest również użycie wyliczenia.
typedef enum { typeNo1 = 1, typeNo2, typeNo3, typeNo4, NumOfTypes = typeNo4 } TypeOfSomething;
źródło
Jak już wyjaśniono w innych odpowiedziach,
const
w języku C oznacza jedynie, że zmienna jest tylko do odczytu. Nadal jest to wartość czasu wykonywania. Możesz jednak użyćenum
jako rzeczywistej stałej w C:enum { NUM_TYPES = 4 }; static int types[NUM_TYPES] = { 1, 2, 3, 4 };
źródło
Imho, to jest wada w wielu kompilatorach C. Wiem na pewno, że kompilatory, z którymi pracowałem, nie przechowują zmiennej „static const” pod adresem, ale zastępują użycie w kodzie bardzo stałą. Można to zweryfikować, ponieważ uzyskasz tę samą sumę kontrolną dla wygenerowanego kodu, gdy używasz dyrektywy #define preprocesorów i gdy używasz statycznej zmiennej const.
Tak czy inaczej, należy używać statycznych zmiennych const zamiast #defines, gdy tylko jest to możliwe, ponieważ statyczna stała jest bezpieczna dla typu.
źródło
static const
zmiennej. Zachowanie, które opisujesz, może być prawidłową optymalizacją, ale z pewnością nie jest czymś, co zawsze może działać.