Comment initialiser tous les membres d’un tableau à la même valeur?

J’ai un grand tableau en C (pas en C ++ si cela fait une différence). Je veux initialiser tous les membres à la même valeur. Je pourrais jurer que je savais une fois un moyen simple de le faire. Je pourrais utiliser memset() dans mon cas, mais n’y a-t-il pas un moyen de le faire qui soit intégré à la syntaxe C?

Sauf si cette valeur est 0 (auquel cas vous pouvez omettre une partie de l’initialiseur et que les éléments correspondants seront initialisés à 0), il n’y a pas de moyen facile.

Ne négligez pas la solution évidente, cependant:

 int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }; 

Les éléments avec des valeurs manquantes seront initialisés à 0:

 int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0... 

Donc, cela initialisera tous les éléments à 0:

 int myArray[10] = { 0 }; // all elements 0 

En C ++, une liste d’initialisation vide initialisera également chaque élément à 0. Ceci n’est pas autorisé avec C:

 int myArray[10] = {}; // all elements 0 in C++ 

Rappelez-vous que les objects avec une durée de stockage statique seront initialisés à 0 si aucun initialiseur n’est spécifié:

 static int myArray[10]; // all elements 0 

Et que “0” ne signifie pas nécessairement “tous les bits zéro”, donc utiliser ce qui précède est meilleur et plus portable que memset (). (Les valeurs à virgule flottante seront initialisées à +0, les pointeurs à une valeur nulle, etc.)

Si votre compilateur est GCC, vous pouvez utiliser la syntaxe suivante:

 int array[1024] = {[0 ... 1023] = 5}; 

Consultez la description détaillée: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html

Pour initialiser statiquement un grand tableau avec la même valeur, sans plusieurs copier-coller, vous pouvez utiliser des macros:

 #define VAL_1X 42 #define VAL_2X VAL_1X, VAL_1X #define VAL_4X VAL_2X, VAL_2X #define VAL_8X VAL_4X, VAL_4X #define VAL_16X VAL_8X, VAL_8X #define VAL_32X VAL_16X, VAL_16X #define VAL_64X VAL_32X, VAL_32X int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X }; 

Si vous devez changer la valeur, vous devez effectuer le remplacement à un seul endroit.

Edit: extensions utiles possibles

(avec la permission de Jonathan Leffler )

Vous pouvez facilement généraliser ceci avec:

 #define VAL_1(X) X #define VAL_2(X) VAL_1(X), VAL_1(X) /* etc. */ 

Une variante peut être créée en utilisant:

 #define STRUCTVAL_1(...) { __VA_ARGS__ } #define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__) /*etc */ 

qui fonctionne avec des structures ou des tableaux composés.

 #define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__) struct Pair { char key[16]; char val[32]; }; struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") }; int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) }; 

les noms de macro sont négociables.

Si vous voulez vous assurer que chaque membre du tableau est explicitement initialisé, omettez simplement la dimension de la déclaration:

 int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

Le compilateur déduira la dimension de la liste d’initialisation. Malheureusement, pour les tableaux multidimensionnels, seule la dimension la plus externe peut être omise:

 int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} }; 

est OK, mais

 int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} }; 

n’est pas.

J’ai vu du code qui utilisait cette syntaxe:

 char* array[] = { [0] = "Hello", [1] = "World" }; 

Là où cela devient particulièrement utile, c’est si vous créez un tableau qui utilise des énumérations comme index:

 enum { ERR_OK, ERR_FAIL, ERR_MEMORY }; #define _ITEM(x) [x] = #x char* array[] = { _ITEM(ERR_OK), _ITEM(ERR_FAIL), _ITEM(ERR_MEMORY) }; 

Cela permet de garder les choses en ordre, même si vous écrivez certaines des valeurs d’énumération dans le désordre.

Vous trouverez plus d’informations sur cette technique ici et ici .

 int i; for (i = 0; i < ARRAY_SIZE; ++i) { myArray[i] = VALUE; } 

Je pense que c'est mieux que

 int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5... 

en fonction de la taille des modifications du tableau.

Vous pouvez faire tout l’initialiseur statique comme détaillé ci-dessus, mais cela peut être vraiment désagréable lorsque la taille de votre tableau change (lorsque votre tableau s’emballe, si vous n’ajoutez pas les initialiseurs supplémentaires appropriés, vous obtenez des erreurs).

memset vous donne un access à l’exécution pour faire le travail, mais aucune coupure de code effectuée correctement n’est à l’abri des modifications de la taille du tableau. J’utiliserais cette solution dans presque tous les cas où le tableau était plus grand que, par exemple, quelques dizaines d’éléments.

S’il était vraiment important que le tableau soit déclaré statiquement, j’écrirais un programme pour écrire le programme pour moi et l’intégrer au processus de construction.

Voici une autre façon:

 static void unhandled_interrupt(struct trap_frame *frame, int irq, void *arg) { //this code intentionally left blank } static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = { [0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL}, }; 

Voir:

C-Extensions

Inits désignés

Puis posez la question: Quand peut-on utiliser les extensions C?

L’exemple de code ci-dessus est dans un système intégré et ne verra jamais la lumière d’un autre compilateur.

Pour initialiser les types de données ‘normaux’ (comme les tableaux int), vous pouvez utiliser la notation entre parenthèses, mais elle mettra à zéro les valeurs après le dernier s’il y a encore de l’espace dans le tableau:

 // put values 1-8, then two zeroes int list[10] = {1,2,3,4,5,6,7,8}; 

Une réponse légèrement ironique; écrire la déclaration

 array = initial_value 

dans votre langage de tableau préféré (le mien est Fortran, mais il y en a beaucoup d’autres), et le liez à votre code C. Vous voudrez probablement le transformer en une fonction externe.

Si le tableau arrive à être int ou quelque chose de la taille de int ou si la taille de votre mem-pattern correspond exactement à un int (tous les zéros ou 0xA5A5A5A5), le mieux est d’utiliser memset () .

Sinon, appelez memcpy () dans une boucle en déplaçant l’index.

Il existe un moyen rapide d’initialiser un tableau de tout type avec une valeur donnée. Cela fonctionne très bien avec les grands tableaux. L’algorithme est le suivant:

  • initialiser le premier élément du tableau (manière habituelle)
  • copier la partie qui a été définie dans la partie qui n’a pas été définie, en doublant la taille à chaque opération de copie suivante

Pour 1 000 000 éléments int array, il est 4 fois plus rapide que l’initialisation de la boucle normale (i5, 2 cœurs, 2,3 GHz, mémoire 4GiB, 64 bits):

loop runtime 0.004248 [seconds]

memfill() runtime 0.001085 [seconds]


 #include  #include  #include  #define ARR_SIZE 1000000 void memfill(void *dest, size_t destsize, size_t elemsize) { char *nextdest = (char *) dest + elemsize; size_t movesize, donesize = elemsize; destsize -= elemsize; while (destsize) { movesize = (donesize < destsize) ? donesize : destsize; memcpy(nextdest, dest, movesize); nextdest += movesize; destsize -= movesize; donesize += movesize; } } int main() { clock_t timeStart; double runTime; int i, a[ARR_SIZE]; timeStart = clock(); for (i = 0; i < ARR_SIZE; i++) a[i] = 9; runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC; printf("loop runtime %f [seconds]\n",runTime); timeStart = clock(); a[0] = 10; memfill(a, sizeof(a), sizeof(a[0])); runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC; printf("memfill() runtime %f [seconds]\n",runTime); return 0; } 

Personne n’a mentionné l’ordre d’index pour accéder aux éléments du tableau initialisé. Mon exemple de code lui donnera un exemple illustratif.

 #include  void PrintArray(int a[3][3]) { std::cout << "a11 = " << a[0][0] << "\t\t" << "a12 = " << a[0][1] << "\t\t" << "a13 = " << a[0][2] << std::endl; std::cout << "a21 = " << a[1][0] << "\t\t" << "a22 = " << a[1][1] << "\t\t" << "a23 = " << a[1][2] << std::endl; std::cout << "a31 = " << a[2][0] << "\t\t" << "a32 = " << a[2][1] << "\t\t" << "a33 = " << a[2][2] << std::endl; std::cout << std::endl; } int wmain(int argc, wchar_t * argv[]) { int a1[3][3] = { 11, 12, 13, // The most 21, 22, 23, // basic 31, 32, 33 }; // format. int a2[][3] = { 11, 12, 13, // The first (outer) dimension 21, 22, 23, // may be omitted. The compiler 31, 32, 33 }; // will automatically deduce it. int a3[3][3] = { {11, 12, 13}, // The elements of each {21, 22, 23}, // second (inner) dimension {31, 32, 33} }; // can be grouped together. int a4[][3] = { {11, 12, 13}, // Again, the first dimension {21, 22, 23}, // can be omitted when the {31, 32, 33} }; // inner elements are grouped. PrintArray(a1); PrintArray(a2); PrintArray(a3); PrintArray(a4); // This part shows in which order the elements are stored in the memory. int * b = (int *) a1; // The output is the same for the all four arrays. for (int i=0; i<9; i++) { std::cout << b[i] << '\t'; } return 0; } 

La sortie est la suivante:

 a11 = 11 a12 = 12 a13 = 13 a21 = 21 a22 = 22 a23 = 23 a31 = 31 a32 = 32 a33 = 33 a11 = 11 a12 = 12 a13 = 13 a21 = 21 a22 = 22 a23 = 23 a31 = 31 a32 = 32 a33 = 33 a11 = 11 a12 = 12 a13 = 13 a21 = 21 a22 = 22 a23 = 23 a31 = 31 a32 = 32 a33 = 33 a11 = 11 a12 = 12 a13 = 13 a21 = 21 a22 = 22 a23 = 23 a31 = 31 a32 = 32 a33 = 33 11 12 13 21 22 23 31 32 33 

Vous pouvez utiliser la fonction memset.

 void *memset(void *array, int value, unsigned sizeofarray); 
  1. Si votre tableau est déclaré statique ou global, tous les éléments du tableau ont déjà la valeur par défaut 0 par défaut.
  2. Certains compilateurs définissent le tableau sur 0 par défaut en mode débogage.
  3. Il est facile de définir la valeur par défaut sur 0: int array [10] = {0};
  4. Cependant, pour les autres valeurs, vous devez utiliser memset () ou loop;

exemple: tableau int [10]; memset (array, -1, 10 * sizeof (int));

En parcourant tout le bavardage, la réponse courte est que si vous activez l’optimisation au moment de la compilation, vous ne ferez pas mieux que cela:

 int i,value=5,array[1000]; for(i=0;i<1000;i++) array[i]=value; 

Bonus ajouté: le code est réellement lisible 🙂

 #include int main(){ int i,a[50]; for (i=0;i<50;i++){ a[i]=5;// set value 5 to all the array index } for (i=0;i<50;i++) printf("%d\n",a[i]); return 0; } 

Il donnera le o / p 5 5 5 5 5 5 ...... jusqu'à la taille du tableau entier

Je sais que l’utilisateur Tarski répondu à cette question de la même manière, mais j’ai ajouté quelques détails supplémentaires. Pardonnez une partie de mon C car je suis un peu rouillé car je suis plus enclin à vouloir utiliser le C ++, mais le tour est joué.


Si vous connaissez la taille du tableau à l’avance …

 #include  typedef const unsigned int cUINT; typedef unsigned int UINT; cUINT size = 10; cUINT initVal = 5; void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ); void printArray( UINT* myArray ); int main() { UINT myArray[size]; /* Not initialized during declaration but can be initialized using a function for the appropriate TYPE*/ arrayInitializer( myArray, size, initVal ); printArray( myArray ); return 0; } void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ) { for ( UINT n = 0; n < size; n++ ) { myArray[n] = initVal; } } void printArray( UINT* myArray ) { printf( "myArray = { " ); for ( UINT n = 0; n < size; n++ ) { printf( "%u", myArray[n] ); if ( n < size-1 ) printf( ", " ); } printf( " }\n" ); } 

Il y a quelques mises en garde ci-dessus; l'un est celui UINT myArray[size]; n'est pas directement initialisé lors de la déclaration, cependant le bloc de code ou l'appel de fonction le plus proche initialise chaque élément du tableau à la même valeur que vous voulez. L'autre mise en garde est que vous devez écrire une initializing function pour chaque type vous prendrez en charge et que vous devrez également modifier la fonction printArray() pour prendre en charge ces types.


Vous pouvez essayer ce code avec un complément en ligne trouvé ici .

Je ne vois aucune exigence dans la question, donc la solution doit être générique: initialisation d’un tableau non spécifié, éventuellement multidimensionnel, construit à partir d’éléments de structure non spécifiés avec une valeur de membre initiale:

 #include  void array_init( void *start, size_t element_size, size_t elements, void *initval ){ memcpy( start, initval, element_size ); memcpy( (char*)start+element_size, start, element_size*(elements-1) ); } // testing #include  struct s { int a; char b; } array[2][3], init; int main(){ init = (struct s){.a = 3, .b = 'x'}; array_init( array, sizeof(array[0][0]), 2*3, &init ); for( int i=0; i<2; i++ ) for( int j=0; j<3; j++ ) printf("array[%i][%i].a = %i .b = '%c'\n",i,j,array[i][j].a,array[i][j].b); } 

Résultat:

 array[0][0].a = 3 .b = 'x' array[0][1].a = 3 .b = 'x' array[0][2].a = 3 .b = 'x' array[1][0].a = 3 .b = 'x' array[1][1].a = 3 .b = 'x' array[1][2].a = 3 .b = 'x' 

EDIT: start+element_size changé en (char*)start+element_size