Po pierwsze stwierdziłem, że nie można zdefiniować typu stałej za pomocą #define. Dlaczego tak jest?
Dlaczego co? To nie prawda:
#define MY_INT_CONSTANT ((int) 12345)
Po drugie, czy są jakieś zalety używania jednego z nich nad drugim?
Tak. #definedefiniuje makro, które jest zastępowane jeszcze przed rozpoczęciem kompilacji. constpo prostu modyfikuje zmienną, aby kompilator oznaczył błąd, jeśli spróbujesz go zmienić. Są konteksty, w których możesz użyć a, #defineale nie możesz użyć const(chociaż staram się znaleźć taki, który używa najnowszego clang). Teoretycznie constzajmuje miejsce w pliku wykonywalnym i wymaga odniesienia do pamięci, ale w praktyce jest to nieistotne i może zostać zoptymalizowane przez kompilator.
consts są znacznie bardziej przyjazne dla kompilatorów i debugerów niż #defines. W większości przypadków jest to nadrzędny punkt, który należy wziąć pod uwagę przy podejmowaniu decyzji, którego z nich użyć.
Pomyślałem o kontekście, w którym możesz użyć, #defineale nie const. Jeśli masz stałą, której chcesz użyć w wielu .cplikach, #definepo prostu umieść ją w nagłówku. Z a constmusisz mieć definicję w pliku C i
const int MY_INT_CONST = 12345;
extern const int MY_INT_CONST;
w nagłówku. MY_INT_CONSTnie może być używany jako rozmiar tablicy o zasięgu statycznym lub globalnym w żadnym pliku C, z wyjątkiem tego, w którym jest zdefiniowana.
Jednak w przypadku stałych całkowitych można użyć rozszerzenia enum. W rzeczywistości Apple robi to prawie zawsze. Ma to wszystkie zalety zarówno #defines, jak i consts, ale działa tylko dla stałych całkowitych.
enum
{
MY_INT_CONST = 12345,
};
Wreszcie, który sposób jest bardziej wydajny i / lub bezpieczniejszy?
#definejest bardziej wydajne w teorii, chociaż, jak powiedziałem, nowoczesne kompilatory prawdopodobnie zapewniają, że różnica jest niewielka. #definejest bezpieczniejszy, ponieważ próba przypisania do niego zawsze jest błędem kompilatora
#define FOO 5
FOO = 6;
consts można oszukać, aby zostać przypisanym do, chociaż kompilator może generować ostrzeżenia:
const int FOO = 5;
(int) FOO = 6;
W zależności od platformy przypisanie może nadal zakończyć się niepowodzeniem w czasie wykonywania, jeśli stała jest umieszczona w segmencie tylko do odczytu i jest oficjalnie niezdefiniowanym zachowaniem zgodnie ze standardem C.
Osobiście w przypadku stałych całkowitych zawsze używam enums dla stałych innych typów, używam constchyba, że mam bardzo dobry powód, aby tego nie robić.