C Language
Littéraux composés
Recherche…
Syntaxe
- (type) {liste d'initialisation}
Remarques
C standard dit dans C11-§6.5.2.5 / 3:
Une expression postfixe composée d'un nom de type entre parenthèses suivi d'une accolade contenant une liste d'initialisateurs est un littéral composé . Il fournit un objet non nommé dont la valeur est donnée par la liste d'initialisation. 99)
et la note de bas de page 99 dit:
Notez que cela diffère d'une expression de distribution. Par exemple, un transtypage spécifie une conversion en types scalaires ou nuls uniquement, et le résultat d'une expression de distribution n'est pas une lvalue.
Notez que:
Les littéraux de chaîne et les littéraux composés avec des types qualifiés de constants n'ont pas besoin de désigner des objets distincts. 101)
101) Cela permet aux implémentations de partager le stockage pour les littéraux de chaîne et les littéraux composés constants avec des représentations identiques ou superposées.
L'exemple est donné en standard:
C11-§6.5.2.5 / 13:
Tout comme les littéraux de chaîne, les littéraux composés qualifiés peuvent être placés en mémoire morte et peuvent même être partagés. Par exemple,
(const char []){"abc"} == "abc"
peut donner 1 si le stockage des littéraux est partagé.
Définition / Initialisation des littéraux composés
Un littéral composé est un objet sans nom créé dans la portée où il est défini. Le concept a été introduit pour la première fois dans la norme C99. Un exemple de littéral composé est
Exemples de la norme C, C11-§6.5.2.5 / 9:
int *p = (int [2]){ 2, 4 };
p
est initialisé à l'adresse du premier élément d'un tableau sans nom de deux ints.
Le littéral composé est une lvalue. La durée de stockage de l'objet non nommé est soit statique (si le littéral apparaît dans la portée du fichier), soit automatique (si le littéral apparaît dans la portée du bloc) et dans ce dernier cas la durée de vie de l'objet
void f(void) { int *p; /*...*/ p = (int [2]){ *p }; /*...*/ }
On attribue à
p
l'adresse du premier élément d'un tableau de deux ints, le premier ayant la valeur pointée précédemment parp
et le second, zéro. [...]
Ici, p
reste valide jusqu'à la fin du bloc.
Littéral composé avec désignateurs
(également de C11)
struct point {
unsigned x;
unsigned y;
};
extern void drawline(struct point, struct point);
// used somewhere like this
drawline((struct point){.x=1, .y=1}, (struct point){.x=3, .y=4});
Une ligne de drawline
fictive reçoit deux arguments de type struct point
. Le premier a des valeurs de coordonnées x == 1
et y == 1
, tandis que le second a x == 3
et y == 4
Littéral composé sans spécifier la longueur du tableau
int *p = (int []){ 1, 2, 3};
Dans ce cas, la taille du tableau n'est pas spécifiée, alors elle sera déterminée par la longueur de l'initialiseur.
Littéral composé dont la longueur de l'initialiseur est inférieure à celle spécifiée
int *p = (int [10]){1, 2, 3};
le reste des éléments du littéral composé sera initialisé à 0
implicitement.
Littéral composé en lecture seule
Notez qu'un littéral composé est une lvalue et que ses éléments peuvent donc être modifiables. Un littéral composé en lecture seule peut être spécifié à l'aide du qualificateur const
sous la forme (const int[]){1,2}
.
Littéral composé contenant des expressions arbitraires
À l'intérieur d'une fonction, un littéral composé, comme pour toute initialisation depuis C99, peut avoir des expressions arbitraires.
void foo()
{
int *p;
int i = 2; j = 5;
/*...*/
p = (int [2]){ i+j, i*j };
/*...*/
}