Waarom compileert sizeof(my_arr)[0] en is sizeof(my_arr[0]) gelijk?

Waarom compileert deze code?

_Static uint32_t my_arr[2];
_Static_assert(sizeof(my_arr) == 8, "");
_Static_assert(sizeof(my_arr[0]) == 4, "");
_Static_assert(sizeof(my_arr)[0] == 4, "");

De eerste 2 beweringen zijn duidelijk correct, maar ik had verwacht dat de laatste regel zou mislukken, aangezien ik begrijp dat sizeof()moet worden geëvalueerd naar een letterlijke integer, die niet kan worden behandeld als een array. Met andere woorden, het zou op dezelfde manier mislukken als de volgende regel:

_Static_assert(4[0] == 4, "");

Interessant is dat het volgende inderdaad niet compileert (wat hetzelfde zou moeten doen, niet?):

_Static_assert(*sizeof(my_arr) == 4, "");

fout: ongeldig type argument van unary ‘*’ (hebben ‘long unsigned int’)
_Static_asset(*sizeof(my_arr) == 4, “”);

Als het er toe doet, gebruik ik gcc 5.3.0


Antwoord 1, autoriteit 100%

sizeofis geen functie. Het is een unaire operator zoals !of ~.

sizeof(my_arr)[0]ontleedt als sizeof (my_arr)[0], wat gewoon sizeof my_arr[0]is met overbodige haakjes.

Dit is net zoals !(my_arr)[0]parseert als !(my_arr[0]).

Over het algemeen hebben postfix-operators een hogere prioriteit dan prefix-operators in C. sizeof *a[i]++parseert als sizeof (*((a[i])++))(de postfix-operatoren []en ++worden eerst toegepast op a, daarna de prefix-operatoren *en sizeof).

(Dit is de expressieversie van sizeof. Er is ook een typeversie, die een typenaam tussen haakjes heeft: sizeof (TYPE). In dat geval zouden de haakjes vereist zijn en deel uitmaken van de syntaxis sizeof.)


Antwoord 2, autoriteit 23%

sizeofheeft twee “versies”: sizeof(type name)en sizeof expression. De eerste vereist een paar ()rond zijn argument. Maar de laatste – degene met een uitdrukking als argument – heeft geen ()om zijn argument. Wat voor ()u ook gebruikt in het argument, het wordt gezien als onderdeel van de argumentuitdrukking, niet als onderdeel van de sizeof-syntaxis zelf.

Aangezien my_arrbij de compiler bekend is als een objectnaam, niet als een typenaam, wordt uw sizeof(my_arr)[0]door de compiler gezien als sizeoftoegepast op een expressie: sizeof (my_arr)[0], waarbij (my_arr)[0]de argumentexpressie is. De ()rond de arraynaam is puur overbodig. De hele uitdrukking wordt geïnterpreteerd als sizeof my_arr[0]. Dit komt overeen met uw vorige sizeof(my_arr[0]).

(Dit betekent trouwens dat je vorige sizeof(my_arr[0])ook een paar overbodige ()bevat.)

Het is een nogal wijdverbreide misvatting dat de syntaxis van sizeofop de een of andere manier een paar ()rond het argument vereist. Deze misvatting is wat de intuïtie van mensen misleidt bij het interpreteren van uitdrukkingen als sizeof(my_arr)[0].


Antwoord 3, autoriteit 14%

[]hebben een hogere prioriteit dan sizeof. Dus sizeof(my_arr)[0]is hetzelfde als sizeof((my_arr)[0]).

Hieris een link naar een prioriteitstabel.


Antwoord 4, autoriteit 4%

U gebruikt de versie van de operator sizeofdie een expressie als parameter aanneemt. In tegenstelling tot degene die een type nodig heeft, vereist het geenhaakjes. Daarom is de operand gewoon (my_arr)[0], waarbij de haakjes overbodig zijn.

Other episodes