Domanda

C definisce almeno 3 livelli di "espressione costante":

  • espressione costante (non qualificata)
  • espressione di costante aritmetica
  • espressione costante intera

6.6 paragrafo 3 recita:

Le espressioni costanti non devono contenere assegnazione, incremento, decremento, chiamata di funzione, o virgola, tranne quando sono contenuti in una sottoespressione che non lo è valutato.

Quindi questo significa che 1,2 non è un'espressione costante?

Il paragrafo 8 recita:

Un'espressione di costante aritmetica deve essere di tipo aritmetico e deve avere solo operandi che sono costanti intere, costanti fluttuanti, costanti di enumerazione, carattere costanti e dimensione delle espressioni. Operatori di cast in un'espressione di costante aritmetica converte solo i tipi aritmetici in tipi aritmetici, tranne come parte di un operando in a operatore sizeof il cui risultato è una costante intera.

Quali sono gli operandi in (union { uint32_t i; float f; }){ 1 }.f? Se 1 è l'operando, questa è presumibilmente un'espressione aritmetica costante, ma se { 1 } è l'operando, chiaramente non lo è.

Modifica: Un'altra osservazione interessante: 7.17 paragrafo 3 richiede che il risultato di offsetof sia un'espressione costante intera di tipo size_t, ma le implementazioni standard di offsetof, per quanto ne so, non lo sono necessario per essere espressioni costanti intere dallo standard. Questo ovviamente va bene poiché un'implementazione è consentita (sotto 6.6 paragrafo 10) per accettare altre forme di espressioni costanti, o implementare la macro offsetof come __builtin_offsetof piuttosto che tramite sottrazione del puntatore. L'essenza di questa osservazione, tuttavia, è che se si desidera utilizzare offsetof in un contesto in cui è richiesta un'espressione costante intera, è necessario utilizzare la macro fornita dall'implementazione e non eseguire il rollio personale.

È stato utile?

Soluzione

In base alla tua lettura, 1,2 non è un'espressione costante. Non so perché non lo sia, solo che sono d'accordo con te che non lo è (nonostante il fatto che probabilmente dovrebbe essere).

6.5.2 specifica i letterali composti come operatore suffisso. Quindi in

(union { uint32_t i; float f; }){ 1 }.f

Gli operandi sono (union { uint32_t i; float f; }){ 1 } e f per l'operatore .. Non è un'espressione aritmetica costante, poiché il primo argomento è un tipo union, ma è un'espressione costante.

AGGIORNAMENTO: mi basavo su una diversa interpretazione dello standard.

Il mio precedente ragionamento era che (union { uint32_t i; float f; }){ 1 }.f soddisfaceva i criteri per un'espressione costante, ed era quindi un'espressione costante. Continuo a pensare che soddisfi i criteri per un'espressione costante (6.6 paragrafo 3) ma che non sia uno dei tipi standard di espressioni costanti (intero, aritmetico o indirizzo) ed è quindi soggetto solo ad essere un'espressione costante per 6.6 paragrafo 10, che consente espressioni costanti definite dall'implementazione.

Avevo anche intenzione di accedere alla tua modifica. Stavo per sostenere che l'implementazione "hack" di offsetof era un'espressione costante, ma penso che sia la stessa di sopra: soddisfa i criteri per un'espressione costante (e possibilmente una costante di indirizzo) ma non è un'espressione costante intera, e pertanto non è valido al di fuori del paragrafo 6.6 10.

Altri suggerimenti

Se 1,2 fosse un'espressione costante, ciò consentirebbe la compilazione di codice come questo:

{ // code        // How the compiler interprets:
  int a[10, 10]; // int a[10];

  a[5, 8] = 42;  // a[8] = 42;
}

Non so se sia il vero motivo, ma posso immaginare che l'emissione di un errore per questo errore (comune?) fosse considerato più importante che trasformare 1,2 in un'espressione costante.

AGGIORNAMENTO : come sottolinea R. in un commento, il codice about non è più un errore del compilatore dall'introduzione dei VLA.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top