Qualificateurs de type
Les qualificateurs de type fournissent une des deux propriétés à un identificateur. Le qualificateur de type const
déclare un objet comme étant non modifiable. Le qualificateur de type volatile
déclare un élément dont la valeur peut légitimement être modifiée par quelque chose non contrôlé par le programme dans lequel il apparaît, par exemple un thread s'exécutant simultanément.
Les qualificateurs de type, const
, restrict
et volatile
, ne peuvent apparaître qu'une seule fois dans une déclaration. Ils peuvent apparaître avec n'importe quel spécificateur de type. Toutefois, ils ne peuvent pas apparaître après la première virgule dans une déclaration d'éléments multiples. Par exemple, les déclarations suivantes sont autorisées :
typedef volatile int VI;
const int ci;
Ces déclarations ne sont pas conformes :
typedef int *i, volatile *vi;
float f, const cf;
Les qualificateurs de type sont appropriés uniquement lors de l'accès à des identificateurs sous la forme d'l-values dans des expressions. Consultez Expressions L-value et r-value pour plus d'informations sur les l-values et les expressions.
Syntaxe
type-qualifier
:
const
restrict
volatile
const
et volatile
Voici les déclarations const
et volatile
conformes :
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
Si la spécification d'un type tableau inclut des qualificateurs de type, l'élément est qualifié, pas le type tableau. Si la spécification du type de fonction comprend des qualificateurs, le comportement est non défini. volatile
et const
n’affectent pas la plage de valeurs ou les propriétés arithmétiques de l’objet.
Le mot clé
const
peut être utilisé pour modifier tout type fondamental ou d'agrégat, ou un pointeur vers un objet de tout type, ou untypedef
. Si un élément est déclaré uniquement avec le qualificateur de typeconst
, son type est considéré comme const int. Une variableconst
peut être initialisée ou être placée dans une région de stockage en lecture seule. Le mot cléconst
est utile pour déclarer des pointeurs versconst
, car il interdit à la fonction de modifier le pointeur de quelque manière que ce soit.Le compilateur suppose que, à tout moment dans le programme, une variable
volatile
est accessible par un processus inconnu qui utilise ou modifie sa valeur. Indépendamment des optimisations spécifiées sur la ligne de commande, le code pour chaque assignation ou référence d'une variablevolatile
doit être généré même s'il semble n'avoir aucun effet.
Si volatile
est utilisé seul, int
est pris par défaut. Le spécificateur de type volatile
peut être utilisé pour fournir un accès fiable aux emplacements de mémoire spéciaux. Utilisez volatile
avec des objets de données accessibles ou modifiables par les gestionnaires de signaux, en exécutant simultanément des programmes, ou par un matériel spécial tel que les registres de contrôle d'E/S mappé en mémoire. Vous pouvez déclarer une variable comme volatile
pour toute sa durée de vie, ou vous pouvez effectuer un cast d'une référence unique pour qu'elle soit volatile
.
- Un élément peut être à la fois
const
etvolatile
, auquel cas il ne peut pas être légitimement modifié par son propre programme, mais par un processus asynchrone.
restrict
Le qualificateur de type restrict
, introduit dans C99 et disponible en mode /std:c11
ou /std:c17
, peut être appliqué aux déclarations de pointeur. Il qualifie le pointeur, pas ce sur quoi il pointe.
restrict
est une indication d’optimisation à l’adresse du compilateur indiquant qu’aucun autre pointeur dans l’étendue actuelle ne fait référence au même emplacement de mémoire. Autrement dit, seul le pointeur ou une valeur dérivée de celui-ci (par exemple, pointeur + 1) est utilisé pour accéder à l’objet pendant la durée de vie du pointeur. Cela permet au compilateur de produire du code plus optimisé. C++ a un mécanisme équivalent, __restrict
N’oubliez pas que restrict
est un contrat entre vous et le compilateur. Si vous aliassez un pointeur marqué avec restrict
, le résultat n’est pas défini.
Voici un exemple qui utilise 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;
};
Voir aussi
/std
(Spécifier la version du standard du langage)
Déclarations et types