Kiedy sprawdzamy rozmiar funkcji za pomocą sizeof()
, zawsze otrzymujemy 1 bajt . Co oznacza ten 1 bajt?
Kiedy sprawdzamy rozmiar funkcji za pomocą sizeof()
, zawsze otrzymujemy 1 bajt . Co oznacza ten 1 bajt?
Odpowiedzi:
Jest to naruszenie ograniczenia i Twój kompilator powinien to zdiagnozować. Jeśli mimo to skompiluje, Twój program zachowuje się niezdefiniowane [dzięki @Steve Jessop za wyjaśnienie trybu awarii i zobacz odpowiedź @Michaela Burra, wyjaśniającą, dlaczego niektóre kompilatory na to zezwalają]: From C11, 6.5.3.4./ 1:
sizeof
Operator nie stosuje się do wyrażenia, które ma typ funkcji
-std=c11
, nie gnu11
. To naprawdę dziwne rozszerzenie kompilatora.
sizeof(void)
1 w GNU C.
-std=c11
: ktoś powinien odnieść się do -std=c*
opcji Standardy reklamowe. Nie włączają trybu zgodności, a jedynie wyłączają rozszerzenia, które uniemożliwiałyby kompilację dobrze sformułowanego programu (na przykład jako typeof
słowo kluczowe, ponieważ dobrze sformułowany program w C może używać go jako nazwy zmiennej, ale gcc
domyślnie odrzuciłby to ). Aby dodatkowo wyłączyć rozszerzenia, które pozwalają źle sformułowanym programom przejść niezdiagnozowane, potrzebujesz -pedantic
lub -pedantic-errors
.
To nie jest niezdefiniowane zachowanie - standard języka C wymaga diagnostyki podczas używania sizeof
operatora z desygnatorem funkcji (nazwą funkcji), ponieważ jest to naruszenie ograniczenia dla sizeof
operatora.
Jednak jako rozszerzenie języka C, GCC umożliwia arytmetykę na void
wskaźnikach i wskaźnikach funkcji, co jest wykonywane przez traktowanie rozmiaru a void
lub funkcji jako 1
. W konsekwencji sizeof
operator oceni 1
for void
lub funkcję z GCC. Zobacz http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith
Możesz zmusić GCC do wydawania ostrzeżeń podczas używania sizeof
z tymi operandami, używając opcji -pedantic
lub -Wpointer-arith
w GCC. Lub zrób z tego błąd -Werror=pointer-arith
.
sizeof
funkcja nie jest UB (o czym wspomniałem tylko dlatego, że inne odpowiedzi mówiły, że to UB). Ale może pogmatwałem to ze względu na sposób, w jaki skonstruowałem zdanie. Żeby było jaśniej. sizeof
funkcja nie jest UB (jak twierdziło kilka odpowiedzi). Jest to naruszenie ograniczeń. Jako taki wymaga diagnostyki. GCC dopuszcza to jako rozszerzenie.
Oznacza to, że twórca kompilatora zdecydował się na wartość 1, zamiast sprawiać, że demony latają z twojego nosa (rzeczywiście, było to kolejne nieokreślone użycie, sizeof
które dało nam to wyrażenie: "kompilator C sam MUSI wydać diagnostykę, JEŚLI jest to pierwsza wymagana diagnostyka wynikająca z twojego programu, a następnie MOŻE sama spowodować wylatywanie demonów z twojego nosa (co, nawiasem mówiąc, mogłoby być udokumentowanym komunikatem diagnostycznym) tak samo, jak MOŻE wydać dalszą diagnostykę pod kątem dalszych naruszeń reguł składni lub ograniczeń (lub, w tej sprawie, z dowolnego wybranego przez siebie powodu). ” https://groups.google.com/forum/?fromgroups=#!msg/comp.std.c/ycpVKxTZkgw/S2hHdTbv4d8J
Stąd slangowe określenie "demony nosowe" na wszystko, co kompilator zdecyduje się zrobić w odpowiedzi na niezdefiniowaną konstrukcję. 1
jest nosowym demonem tego kompilatora w tym przypadku.
Jak wskazywali inni, sizeof () może przyjąć dowolny prawidłowy identyfikator, ale nie zwróci prawidłowego (prawdziwie prawdziwego i prawidłowego) wyniku dla nazw funkcji. Co więcej, z całą pewnością może, ale nie musi, skutkować syndromem „wyskakującego z nosa demonów”.
Jeśli chcesz sprofilować rozmiar funkcji programu, sprawdź mapę linkera, którą można znaleźć w katalogu wyników pośrednich (tym, w którym rzeczy są kompilowane do .obj / .o lub gdzie znajduje się wynikowy obraz / plik wykonywalny). Czasami istnieje opcja, aby wygenerować ten plik mapy lub nie ... zależy to od kompilatora / konsolidatora.
Jeśli chcesz mieć rozmiar wskaźnika do funkcji, wszystkie mają ten sam rozmiar, rozmiar słowa adresującego na twoim procesorze.
int x = 1;
ale tylko jeden z nich jest dozwolony dla kompilatora zgodnego ze standardami. Po sizeof()
zastosowaniu do funkcji może, ale nie musi, zwrócić ustawioną wartość, odmówić kompilacji lub zwrócić losową wartość na podstawie tego, co w danym momencie znajduje się w określonym rejestrze. Dosłowne demony nosowe są mało prawdopodobne, ale mieszczą się w literach normy.
sizeof
wskaźnik do funkcji.
-pedantic
), masz niezgodny kompilator i każdy program ma niezdefiniowane zachowanie.