Perché sizeof int è sbagliato, mentre sizeof (int) è giusto?


96

Sappiamo che sizeofè un operatore utilizzato per calcolare la dimensione di qualsiasi tipo di dato ed espressione, e quando l'operando è un'espressione, le parentesi possono essere omesse.

int main()
{
        int a;

        sizeof int;
        sizeof( int );
        sizeof a;
        sizeof( a );

        return 0;
}

il primo utilizzo di sizeofè sbagliato, mentre altri hanno ragione.

Quando viene compilato utilizzando gcc, verrà fornito il seguente messaggio di errore:

main.c:5:9: error: expected expression before int

La mia domanda è perché lo standard C non consente questo tipo di operazione. Voleresizeof int ambiguità?


5
La cosa divertente è che non tutte le espressioni sono accettate senza parentesi: prova sizeof (int)a.
Fred Foo,

2
@MikkelK .: OP chiede spiegazioni dietro le citazioni standard che conosce già le virgolette che sono menzionate nella risposta contrassegnata.
Alok Save

2
@ Lundin: sizeof +(int)aha il vantaggio rispetto *&alla compilazione effettiva ;-)
Steve Jessop,

2
@SteveJessop Ah, giusto, non è un lvalue. Sebbene sia stato compilato in Embarcadero C ++, stranamente. Ad ogni modo, credo che solo ora abbiamo trovato un uso per l'operatore unario +! Quella deve essere la prima volta nella storia della programmazione C :)
Lundin

2
@ Lundin: devi ancora stare attento con unario +. Ad esempio, a sizeof +(char)a == sizeof(int)causa della promozione di numeri interi, è probabilmente meno soggetto a errori solo da mettere tra parentesi se c'è qualche preoccupazione per l'espressione di cui stai cercando di prendere la dimensione. Quindi non sono sicuro che sarei arrivato al punto di chiamarlo "un uso", anche se ammetto di averlo usato ...
Steve Jessop

Risposte:


101

Quanto segue potrebbe essere ambiguo:

sizeof int * + 1

È quello (sizeof (int*)) + 1o (sizeof(int)) * (+1)?

Ovviamente il linguaggio C avrebbe potuto introdurre una regola per risolvere l'ambiguità, ma posso immaginare perché non ha dato fastidio. Con la lingua così com'è, un identificatore di tipo non appare mai "nudo" in un'espressione, quindi non sono necessarie regole per stabilire se quel secondo* fa parte del tipo o un operatore aritmetico.

La grammatica esistente risolve già la potenziale ambiguità di sizeof (int *) + 1. Si tratta (sizeof(int*))+1, non è sizeof((int*)(+1)) .

C ++ ha un problema in qualche modo simile da risolvere con la sintassi cast in stile funzione. Puoi scrivere int(0)e puoi scrivere typedef int *intptr; intptr(0);, ma non puoi scrivere int*(0). In questo caso, la risoluzione è che il tipo "nudo" deve essere un semplice nome di tipo, non può essere solo un vecchio tipo di id che potrebbe contenere spazi o punteggiatura finale. Forse sizeofavrebbe potuto essere definito con la stessa restrizione, non ne sono certo.


1
C ++ ha new int*(X)che sarebbe ambiguo se C ++ non specificasse che il nuovo operatore accetta la stringa più lunga che potrebbe essere un tipo. Quindi in C ++ avrebbero potuto fare lo stesso con sizeof, immagino. Ma in C ++ puoi dire sizeof int()quale sarebbe stato ambiguo (tipo o valore inizializzato int?).
Johannes Schaub - litb

@ JohannesSchaub-litb: Mmm, quindi forse C ++ potrebbe dire che il tipo è preferito se è possibile analizzarne uno, altrimenti è un'espressione. L'ambiguità verrebbe risolta ma sizeof int()sarebbe mal formata ("no operator()per size_t"), cosa che mi aspetto sarebbe sgradita!
Steve Jessop

32

Dallo standard C99

6.5.3.4.2
L' sizeofoperatore restituisce la dimensione (in byte) del suo operando, che può essere un'espressione o il nome tra parentesi di un tipo.

Nel tuo caso intnon è né espressione né nome tra parentesi.


10
Non capisco perché questo ottiene 7 voti positivi. Come le tre risposte eliminate, si limita a ripetere la regola invece di spiegare perché la regola esiste.
Fred Foo

7
@larsmans, sì, sono d'accordo con te. Anche se continua a ripetere la regola, ma almeno, dà un pezzo di autorizzazione alla lettura.
Yishu Fang

3
@larsmans Se iniziamo a cercare di giustificare ogni decisione presa in C99 saremo qui tutto l'anno. Citando lo standard è un modo buono come un altro per concludere questa discussione.
Perry

1
@Perry: se non ti piace questo tipo di domanda, puoi votare per chiudere la domanda come polemica.
Fred Foo

4
Come non praticante di C ++, anche io capisco questa risposta, non sono sicuro di quale sia il problema se riesci a leggere e comprendere l'inglese.
Kev

6

Ci sono due modi per usare l'operatore sizeof in C. La sintassi è questa:

C11 6.5.3 Unary operators
...
sizeof unary-expression
sizeof ( type-name )

Ogni volta che usi un tipo come operando, devi avere le parentesi, in base alla definizione della sintassi della lingua. Se usi sizeof su un'espressione, non hai bisogno delle parentesi.

Lo standard C fornisce uno di questi esempi di dove potresti volerlo usare su un'espressione:

sizeof array / sizeof array[0]

Tuttavia, per motivi di coerenza e per evitare bug relativi alla precedenza degli operatori, consiglierei personalmente di usare sempre () indipendentemente dalla situazione.


@ JohannesSchaub-litb Sono d'accordo che non fornisce alcuna motivazione per il modo in cui il comitato dello standard C ha ragionato quando ha specificato lo standard C90. Dovresti chiedere loro ... Risponde senza alcuna motivazione fornita, tuttavia, C non lo consente poiché la sintassi è quella specificata in 6.5.3. Anche l'OP sembrava inconsapevole della differenza tra sizeof expressione sizeof(type), che è spiegata in questa risposta.
Lundin

(Per la cronaca, ho appena letto entrambi i razionali C90 e C11 e nessuno dei due fornisce alcuna spiegazione.)
Lundin

Sospetto che non ci sia una logica necessaria per questo, è solo il modo in cui i progettisti C originali hanno deciso di farlo. Forse ha reso le cose più facili per i primi analizzatori. Stavo per pubblicare una risposta sul fatto che i typedef e le variabili condividono lo stesso spazio dei nomi, ma ciò non preclude di consentire la prima sintassi; ha solo bisogno delle regole di analisi per dire che preferisce la variabile quando non ci sono parentesi, preferisce il tipo quando ci sono, e entrambe le forme possono essere utilizzate quando il nome non è ambiguo. Poiché non è necessario cambiarlo, i comitati per gli standard lo hanno lasciato in pace.
Barmar
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.