C Language
Initialisation
Recherche…
Initialisation des variables en C
En l'absence d'initialisation explicite, les variables externes et static
sont garanties pour être initialisées à zéro; Les variables automatiques (y compris register
variables de register
) ont des valeurs initiales indéterminées 1 (c.-à-d.
Les variables scalaires peuvent être initialisées lorsqu'elles sont définies en suivant le nom avec un signe égal et une expression:
int x = 1;
char squota = '\'';
long day = 1000L * 60L * 60L * 24L; /* milliseconds/day */
Pour les variables externes et static
, l'initialiseur doit être une expression constante 2 ; l'initialisation est faite une fois, conceptuellement avant le début de l'exécution du programme.
Pour les variables automatiques et de register
, l'initialiseur n'est pas limité à une constante: il peut s'agir de toute expression impliquant des valeurs précédemment définies, voire des appels de fonctions.
Par exemple, voir l'extrait de code ci-dessous
int binsearch(int x, int v[], int n)
{
int low = 0;
int high = n - 1;
int mid;
...
}
au lieu de
int low, high, mid;
low = 0;
high = n - 1;
En effet, l'initialisation des variables automatiques n'est qu'un raccourci pour les instructions d'affectation. Quelle forme préférer est en grande partie une question de goût. Nous utilisons généralement des affectations explicites, car les initialiseurs dans les déclarations sont plus difficiles à voir et plus éloignés du point d'utilisation. Par contre, les variables ne doivent être déclarées que lorsqu'elles sont sur le point d'être utilisées, dans la mesure du possible.
Initialiser un tableau:
Un tableau peut être initialisé en suivant sa déclaration avec une liste d'initialisateurs entre accolades et séparés par des virgules.
Par exemple, pour initialiser un tableau days avec le nombre de jours de chaque mois:
int days_of_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
(Notez que janvier est encodé en mois zéro dans cette structure.)
Lorsque la taille du tableau est omise, le compilateur calcule la longueur en comptant les initialiseurs, qui sont au nombre de 12 dans ce cas.
S'il y a moins d'initialiseurs pour un tableau que la taille spécifiée, les autres seront nuls pour tous les types de variables.
C'est une erreur d'avoir trop d'initialiseurs. Il n'y a pas de méthode standard pour spécifier la répétition d'un initialiseur - mais GCC a une extension pour le faire.
Dans C89 / C90 ou les versions antérieures de C, il était impossible d'initialiser un élément au milieu d'un tableau sans fournir toutes les valeurs précédentes.
Avec C99 et supérieur, les initialiseurs désignés vous permettent d'initialiser des éléments arbitraires d'un tableau, en laissant toutes les valeurs non initialisées comme des zéros.
Initialisation des tableaux de caractères:
Les tableaux de caractères sont un cas particulier d'initialisation. une chaîne peut être utilisée à la place des accolades et des virgules:
char chr_array[] = "hello";
est un raccourci pour le plus long mais équivalent:
char chr_array[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
Dans ce cas, la taille du tableau est de six (cinq caractères plus le '\0'
).
1 Qu'advient-il d'une variable déclarée non initialisée dans C? At-il une valeur?
2 Notez qu'une expression constante est définie comme quelque chose qui peut être évalué à la compilation. Donc, int global_var = f();
est invalide. Une autre idée fausse commune est de penser une variable qualifiée de const
comme une expression constante . Dans C, const
signifie "lecture seule" et non "constante de compilation". Ainsi, les définitions globales comme const int SIZE = 10; int global_arr[SIZE];
et const int SIZE = 10; int global_var = SIZE;
ne sont pas légales en C.
Initialisation des structures et des tableaux de structures
Les structures et les tableaux de structures peuvent être initialisés par une série de valeurs entre accolades, une valeur par membre de la structure.
struct Date
{
int year;
int month;
int day;
};
struct Date us_independence_day = { 1776, 7, 4 };
struct Date uk_battles[] =
{
{ 1066, 10, 14 }, // Battle of Hastings
{ 1815, 6, 18 }, // Battle of Waterloo
{ 1805, 10, 21 }, // Battle of Trafalgar
};
Notez que l'initialisation du tableau pourrait être écrite sans les accolades intérieures, et dans le passé (avant 1990, par exemple) aurait souvent été écrit sans eux:
struct Date uk_battles[] =
{
1066, 10, 14, // Battle of Hastings
1815, 6, 18, // Battle of Waterloo
1805, 10, 21, // Battle of Trafalgar
};
Bien que cela fonctionne, ce n'est pas un bon style moderne - vous ne devez pas essayer d'utiliser cette notation dans le nouveau code et corriger les avertissements du compilateur qu'elle génère habituellement.
Voir aussi les initialiseurs désignés .
Utiliser des initialiseurs désignés
C99 a introduit le concept d' initialiseurs désignés. Cela vous permet de spécifier quels éléments d'un tableau, d'une structure ou d'une union doivent être initialisés par les valeurs suivantes.
Initialiseurs désignés pour les éléments de tableau
Pour un type simple comme plain int
:
int array[] = { [4] = 29, [5] = 31, [17] = 101, [18] = 103, [19] = 107, [20] = 109 };
Le terme entre crochets, qui peut être n'importe quelle expression entière constante, spécifie quel élément du tableau doit être initialisé par la valeur du terme après le signe =
. Les éléments non spécifiés sont initialisés par défaut, ce qui signifie que des zéros sont définis. L'exemple montre les initialiseurs désignés dans l'ordre; ils ne doivent pas nécessairement être en ordre. L'exemple montre des lacunes; ceux-ci sont légitimes. L'exemple ne montre pas deux initialisations différentes pour le même élément; cela est également autorisé (ISO / CEI 9899: 2011, §6.7.9 Initialisation, ¶19 L'initialisation doit avoir lieu dans l'ordre de la liste d'initialisation, chaque initialiseur étant fourni pour un sous-objet particulier remplaçant tout initialiseur précédemment listé pour le même sous-objet ).
Dans cet exemple, la taille du tableau n'est pas explicitement définie. Par conséquent, l'index maximal spécifié dans les initialiseurs désignés détermine la taille du tableau, ce qui correspond à 21 éléments dans l'exemple. Si la taille était définie, l'initialisation d'une entrée au-delà de la fin du tableau serait une erreur, comme d'habitude.
Initialiseurs désignés pour les structures
Vous pouvez spécifier quels éléments d'une structure sont initialisés à l'aide de .
notation d' element
:
struct Date
{
int year;
int month;
int day;
};
struct Date us_independence_day = { .day = 4, .month = 7, .year = 1776 };
Si les éléments ne sont pas répertoriés, ils sont initialisés par défaut (mis à zéro).
Initialiseur désigné pour les syndicats
Vous pouvez spécifier quel élément d'une union est initialisé avec un initialiseur désigné.
Avant la norme C, il n'y avait aucun moyen d'initialiser une union
. La norme C89 / C90 vous permet d’initialiser le premier membre d’une union
- le choix du membre est donc le premier.
struct discriminated_union
{
enum { DU_INT, DU_DOUBLE } discriminant;
union
{
int du_int;
double du_double;
} du;
};
struct discriminated_union du1 = { .discriminant = DU_INT, .du = { .du_int = 1 } };
struct discriminated_union du2 = { .discriminant = DU_DOUBLE, .du = { .du_double = 3.14159 } };
Notez que C11 vous permet d'utiliser des membres d'union anonymes dans une structure, de sorte que vous n'avez pas besoin du
nom du
dans l'exemple précédent:
struct discriminated_union
{
enum { DU_INT, DU_DOUBLE } discriminant;
union
{
int du_int;
double du_double;
};
};
struct discriminated_union du1 = { .discriminant = DU_INT, .du_int = 1 };
struct discriminated_union du2 = { .discriminant = DU_DOUBLE, .du_double = 3.14159 };
Initialiseurs désignés pour les tableaux de structures, etc.
Ces constructions peuvent être combinées pour des tableaux de structures contenant des éléments tels que des tableaux, etc. L'utilisation d'ensembles complets d'accolades permet de s'assurer que la notation n'est pas ambiguë.
typedef struct Date Date; // See earlier in this example
struct date_range
{
Date dr_from;
Date dr_to;
char dr_what[80];
};
struct date_range ranges[] =
{
[3] = { .dr_from = { .year = 1066, .month = 10, .day = 14 },
.dr_to = { .year = 1066, .month = 12, .day = 25 },
.dr_what = "Battle of Hastings to Coronation of William the Conqueror",
},
[2] = { .dr_from = { .month = 7, .day = 4, .year = 1776 },
.dr_to = { .month = 5, .day = 14, .year = 1787 },
.dr_what = "US Declaration of Independence to Constitutional Convention",
}
};
Spécification de plages dans les initialiseurs de tableau
GCC fournit une extension qui vous permet de spécifier une plage d'éléments dans un tableau devant recevoir le même initialiseur:
int array[] = { [3 ... 7] = 29, 19 = 107 };
Les points triples doivent être séparés des nombres, au cas où l'un des points ne serait pas interprété comme faisant partie d'un nombre à virgule flottante (règle de maximalisation maximale ).