2010-09-20 13 views

risposta

12

Un'espressione costante può essere valutata in fase di compilazione. Ciò significa che non ha variabili in esso. Ad esempio:

5 + 7/3 

è un'espressione costante. Qualcosa di simile:

5 + someNumber/3 

non è, supponendo someNumber è una variabile (cioè, non di per sé una fase di compilazione costante).

+0

Grazie mille Carl, estremamente utile! :) –

+2

L'* indirizzo * di alcune variabili può essere in un'espressione costante, sebbene (quelle con durata di memorizzazione statica). – caf

14

C'è un'altra sottigliezza nelle espressioni costanti. Ci sono alcune cose che sono note al compilatore, ma non possono essere conosciute dal preprocessore.

Ad esempio (24*60*60) può essere calcolato da entrambi, ma sizeof struct foo è noto solo al compilatore. Questa distinzione può essere importante se si sta tentando di verificare che uno struct sia definito per soddisfare una dimensione con obbligo esterno o che i suoi membri siano associati a offset specificati esternamente. (Questo caso di utilizzo spesso sorge quando codifica i driver di periferica in cui la struct descrive dispositivo registra come spiegate nello spazio di memoria.)

In quel caso non si può semplicemente dire #if (sizeof(struct UART) == 12) perché il preprocessore funziona a un passaggio davanti alla compilazione e semplicemente non può conoscere la dimensione di qualsiasi tipo. È, tuttavia, un'espressione costante e sarebbe valida come inizializzazione di una variabile globale (ad esempio int UARTwords = sizeof(struct UART)/sizeof(short);), o di dichiarare la dimensione di un array (ad esempio unsigned char UARTmirror[sizeof(struct UART)];)

+1

+1, quelli che il preprocessore non può gestire sono chiamati 'espressioni costanti limitate', credo. –

+0

@Carl: bello sapere, grazie. Le "espressioni costanti ristrette" sono definite in qualche riferimento? Non lo trovo nello standard C11. – Tim

+0

Ciao @Tim, non ho una specifica a portata di mano, ma Microsoft ha qualcosa qui: https://docs.microsoft.com/en-ca/cpp/c-language/c-constant-expressions –

3

Qualunque singolo valore letterale è un'espressione costante.

3  0.0f '\n' 

(stringhe letterali sono strani, perché sono in realtà gli array. Sembra "hello" in realtà non è una costante, in quanto finisce per dover essere collegati e tutto ciò che, e l'indirizzo e il contenuto può cambiare in fase di esecuzione .)

La maggior parte degli operatori (sizeof, cast, ecc.) Applicati a costanti o tipi sono espressioni costanti.

Qualsiasi espressione che coinvolge solo espressioni costanti è anch'essa un'espressione costante.

15 + 3 
0.0f + 0.0f 
sizeof(char) 

Qualsiasi espressione contenente chiamate di funzione o espressioni non costanti è solitamente non un'espressione costante.

strlen("hello") 
fifteen + x 

Lo stato di qualsiasi macro come espressione costante dipende da cosa si espande.

/* Always a constant */ 
#define FIFTEEN 15 

/* Only constant if (x) is 
#define htons(x) ((((x) >> 8) | ((x) << 8)) & 0xffff) 

/* Never constant */ 
#define X_LENGTH strlen(x) 

Inizialmente avevo alcune cose in qui circa const identificatori, ma ho provato che e apparentemente non si applica in C. const, stranamente, non dichiarare le costanti (almeno, non quelli "costante "sufficiente per essere utilizzato nelle istruzioni switch). In C++, tuttavia, lo fa.

+0

Nota che sizeof () è * sempre * un'espressione costante, anche se l'argomento è un'espressione non const, poiché è il * tipo * sull'espressione che è l'argomento, non l'espressione stessa. – Clifford

+0

@Clifford: in 'C99', sizeof applicato a un VLA non specifica una costante" 6.5.3.4 ... Se il tipo dell'operando è un tipo di array di lunghezza variabile, l'operando viene valutato, altrimenti l'operando non è valutato e il risultato è una costante intera. " – pmg

+0

@cHao: 'const' è un qualificatore di tipo. Si applica agli oggetti ... e nessun oggetto può essere una costante. – pmg

2

Un'altra ruga divertente: in C, il valore di un 'enum' è una costante, ma può essere utilizzato solo dopo che la dichiarazione dell '"enum" è completa. Di seguito, per esempio, non è accettabile in serie C, anche se è accettabile in C++:

 
enum {foo=19, bar, boz=bar+5;}; 

Potrebbe essere riscritta:

 
enum {foo=19, bar}; enum {boz=bar+5;}; 

se questo finirebbe definire più tipi di enumerazione diversi, piuttosto che uno che contiene tutti i valori.

+0

Giusto per dire che queste costanti 'enum' hanno tipo' int'. –

2

Anche integral character constants come 'a' o '\n' sono costanti che il compilatore riconosce come tali. Hanno tipo int.

4

Nessuno sembra aver menzionato ancora un altro tipo di espressione costante: costanti di indirizzo. L'indirizzo di un oggetto con la durata di archiviazione statica è una costante indirizzo, quindi si può fare questo genere di cose nell'ambito di file:

char x; 
char *p = &x; 

stringhe letterali definiscono le matrici con la durata di archiviazione statica, quindi questa regola è anche il motivo per cui si può fare questo per lo scopo del file:

char *s = "foobar"; 
+1

+1, ma è opportuno notare che questo tipo di espressione costante di solito non è ** una costante effettiva in fase di compilazione, e forse non al momento del collegamento se si utilizza il collegamento dinamico. Nella maggior parte delle implementazioni del mondo reale, risulta in una * ricollocazione *. –

+0

Questo è quello che stavo cercando! – abhiarora

Problemi correlati