Condividi tramite


Qualificatori di tipo

I qualificatori di tipo forniscono una delle due proprietà a un identificatore. Il const qualificatore di tipo dichiara un oggetto come non modificabile. Il qualificatore di tipo volatile dichiara un elemento il cui valore può essere modificato legittimamente da un elemento sotto il controllo del programma in cui è visualizzato, ad esempio un thread contemporaneamente in esecuzione.

I qualificatori di tipo, const, restricte volatilepossono essere visualizzati una sola volta in una dichiarazione. I qualificatori di tipo possono essere visualizzati con qualsiasi identificatore di tipo; tuttavia, non possono essere visualizzati dopo la prima virgola in una dichiarazione di più elementi. Ad esempio le seguenti dichiarazioni sono valide:

typedef volatile int VI;
const int ci;

Queste dichiarazioni non sono legali:

typedef int *i, volatile *vi;
float f, const cf;

I qualificatori di tipo sono rilevanti solo in caso di accesso agli identificatori come l-value nelle espressioni. Per informazioni su l-value ed espressioni, vedere Espressioni L-Value e R-Value.

Sintassi

type-qualifier:
const
restrict
volatile

const e volatile

Di seguito sono riportate le dichiarazioni legali const e volatile :

int const *p_ci;      // Pointer to constant int
int const (*p_ci);   // Pointer to constant int
int *const cp_i;     // Constant pointer to int
int (*const cp_i);   // Constant pointer to int
int volatile vint;     // Volatile integer

Se la specifica di un tipo matrice include i qualificatori di tipo, viene qualificato l'elemento, non il tipo di matrice. Se la specifica del tipo di funzione include i qualificatori, il comportamento non è definito. volatile e const non influiscono sull'intervallo di valori o proprietà aritmetiche dell'oggetto.

  • La const parola chiave può essere usata per modificare qualsiasi tipo fondamentale o aggregato o un puntatore a un oggetto di qualsiasi tipo o a un oggetto typedef. Se un elemento viene dichiarato solo con il const qualificatore di tipo, viene visualizzato il relativo tipo come const int. Una const variabile può essere inizializzata o può essere inserita in un'area di archiviazione di sola lettura. La const parola chiave è utile per dichiarare i puntatori a const perché richiede che la funzione non modifichi in alcun modo il puntatore.

  • Il compilatore presuppone che, in un punto qualsiasi del programma, a una variabile volatile possa accedere un processo sconosciuto che utilizza o modifica il valore. Indipendentemente dalle ottimizzazioni specificate nella riga di comando, il codice per ogni assegnazione o riferimento di una volatile variabile deve essere generato anche se sembra non avere alcun effetto.

Se volatile viene utilizzato da solo, viene utilizzato int. L'identificatore di tipo volatile può essere utilizzato per fornire accesso affidabile a posizioni di memoria speciali. Utilizzare volatile con oggetti dati a cui è possibile accedere o che possono essere modificati dai gestori del segnale, mediante l'esecuzione contemporanea di programmi o mediante hardware speciale come i registri di I/O mappati alla memoria. È possibile dichiarare una variabile come volatile per la sua durata oppure eseguire il cast di un solo riferimento che sia volatile.

  • Un elemento può essere sia const e volatile, nel qual caso l'elemento non può essere modificato legittimamente dal proprio programma, ma può essere modificato da un processo asincrono.

restrict

Il restrict qualificatore di tipo, introdotto in C99 e disponibile in /std:c11 modalità o /std:c17 , può essere applicato alle dichiarazioni del puntatore. Qualifica il puntatore, non quello a cui punta.

restrict è un hint di ottimizzazione per il compilatore che nessun altro puntatore nell'ambito corrente fa riferimento alla stessa posizione di memoria. Ovvero, solo il puntatore o un valore derivato da esso (ad esempio puntatore + 1) viene usato per accedere all'oggetto durante la durata del puntatore. Ciò consente al compilatore di produrre codice più ottimizzato. C++ ha un meccanismo equivalente, __restrict

Tenere presente che restrict è un contratto tra l'utente e il compilatore. Se si esegue l'alias di un puntatore contrassegnato con restrict, il risultato non è definito.

Di seguito viene mostrato un esempio che usa restrict:

void test(int* restrict first, int* restrict second, int* val)
{
    *first += *val;
    *second += *val;
}

int main()
{
    int i = 1, j = 2, k = 3;
    test(&i, &j, &k);

    return 0;
}

// Marking union members restrict tells the compiler that
// only z.x or z.y will be accessed in any scope, which allows
// the compiler to optimize access to the members.
union z 
{
    int* restrict x;
    double* restrict y;
};

Vedi anche

/std (Specificare la versione standard del linguaggio)
Dichiarazioni e tipi