Kiedy sprawdzamy rozmiar funkcji za pomocą sizeof()
, zawsze otrzymujemy 1 bajt . Co oznacza ten 1 bajt?
87
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
-pedantic
), masz niezgodny kompilator i każdy program ma niezdefiniowane zachowanie.-std=c11
, niegnu11
. 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 jakotypeof
słowo kluczowe, ponieważ dobrze sformułowany program w C może używać go jako nazwy zmiennej, alegcc
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 dlasizeof
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 avoid
lub funkcji jako1
. W konsekwencjisizeof
operator oceni1
forvoid
lub funkcję z GCC. Zobacz http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-ArithMoż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
.źródło
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/S2hHdTbv4d8JStą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.źródło
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.
źródło
int x = 1;
ale tylko jeden z nich jest dozwolony dla kompilatora zgodnego ze standardami. Posizeof()
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.