Dlaczego (i kiedy) muszę używać nawiasów po sizeof?

80

Poniższe nie można skompilować:

ale jeśli zmienię to na

wszystko w porządku. Czemu?

blueshift
źródło
rozmiar jako operator nie jest dostępny w ansi-c
ponury
2
@Kostya: moja kopia K&R (najwcześniejszy opis języka C, jaki mam) jest bardzo odległa i nie mogę jej teraz sprawdzić, ale jestem w 110% pewna, że sizeofzasadniczo opisuje to samo, co C99 Standard dzisiaj. sizeofjest dostępny, zanim C został znormalizowany przez ANSI w 1989 r.
pmg

Odpowiedzi:

120

Zgodnie z 6.5.3 istnieją dwa formularze sizeof:

Ponieważ arrw twoim kodzie jest a type-name, musi być umieszczony w nawiasach.

Ise Wisteria
źródło
15
+1 i, żeby podkreślić, że sizeofjest to operator: nawias „należy” do typu, a nie do operatora.
pmg
@pmg: Dzięki za wyjaśnienie! Tak, jak wspomniałeś, standard oznacza sizeofoperatora.
Ise Wisteria
4
@pmg: Nie wydaje mi się, żeby było jasne, do czego „należą” nawiasy. Składni drugiej postaci składa się z trzech znaczników i jeden nie-końcowy: sizeof ( type-name ). Ale dla pierwszej postaci, to może napisać, na przykład, sizeof(x)i choć wygląda wywołania funkcji (jeśli sizeofnie były kluczowe), to naprawdę operator stosowane do ekspresji w nawiasy. Czy to miałeś na myśli?
Keith Thompson,
3
Chodzi mi o to, że sizeofsyntaktycznie sizeof <SOMETHING>w przeciwieństwie do funkcji, na przykład a, printfktóre jest printf ( <SOMETHING> ). Nawiasy należą do, printfale nie do sizeof. Kiedy sizeofjest stosowany do nazwy typu w nawiasach, lubię myśleć o tym jako o rzucie niczego - „zwracaniu” tylko typu.
pmg,
2
@pmg: Z pewnością możesz o tym myśleć w ten sposób, ale uważam to za mylące. Jedynym prawdziwym podobieństwem do rzutowania jest to, że ma nazwę typu w nawiasach, a to tylko zbieg okoliczności ze składniowej wygody. Wolę myśleć o tym sizeof ( type-name )jako o swoim własnym rodzaju ekspresji. (Standard nazywa go operatorem, ale ( type-name )tak naprawdę nie jest operandem w zwykłym sensie).
Keith Thompson,
44

W ten sposób określa się język, nazwy typów muszą być tutaj umieszczone w nawiasach.

Załóżmy, że gramatyka wyglądała tak:

sizeof unary-expression sizeof type-name

Teraz np. Następujące wyrażenie byłoby niejednoznaczne:

Może to być albo sizeof(int *) + 0albosizeof(int) * +0 . Ta niejednoznaczność nie występuje w przypadku wyrażeń jednoargumentowych, ponieważ gwiazdka dołączona do wyrażenia nie jest wyrażeniem (ale w przypadku niektórych nazw typów dołączenie jednego jest ponownie nazwą typu).

Coś musiało zostać tutaj określone, a wymaganie, aby nazwy typów były umieszczane w nawiasach, jest sposobem na rozwiązanie niejednoznaczności.

mafso
źródło
-3

Myślę, że to dlatego, że masz typedef. Jeśli go usuniesz, powinien się skompilować.

Przykład z wikipedii:

baz
źródło