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


J'ai un grand tableau en C (pas C ++ si cela fait une différence). Je veux initialiser tous les membres à la même valeur. Je pourrais jurer que j'ai connu 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 est intégré dans la syntaxe C?


789
2017-10-14 13:13


origine


Réponses:


Sauf si cette valeur est 0 (auquel cas vous pouvez omettre une partie de l'initialiseur et 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, ceci initialisera tous les éléments à 0:

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

En C ++, une liste d'initialisation vide initialise également chaque élément à 0. C'est interdit avec C:

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

Rappelez-vous que les objets avec une durée de stockage statique seront initialisés à 0 si aucun l'initialisateur est spécifié:

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

Et ce "0" ne signifie pas nécessairement "tout-bits-zéro", donc en utilisant ce qui précède est mieux et plus portable que memset (). (Les valeurs de virgule flottante seront initialisé à +0, pointeurs vers une valeur nulle, etc.)


1028
2017-10-14 13:17



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


348
2017-10-16 07:38



Pour initialiser statiquement un grand tableau avec la même valeur, sans copier-coller multiple, 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: possibles extensions utiles

(avec l'aimable autorisation 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 */ 

cela 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.


161
2017-10-14 10:27



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.


59
2017-10-14 18:30



J'ai vu du code qui utilisait cette syntaxe:

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

Là où cela devient particulièrement utile est si vous faites un tableau qui utilise enums 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 garde les choses en ordre, même si vous écrivez certaines des valeurs énumérées dans le désordre.

Plus d'informations sur cette technique peuvent être trouvées ici et ici.


45
2018-03-21 21:02



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...

Incase la taille des changements de tableau.


22
2017-10-14 13:34



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

memset vous donne un coup d'exécution pour faire le travail, mais aucun coup de taille de code effectué correctement n'est immunisé contre les changements de taille de tableau. J'utiliserais cette solution dans presque tous les cas lorsque la matrice était plus grande que, disons, quelques douzaines 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.


11
2017-10-14 13:29



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 des extensions C?

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


8
2017-10-14 22:12



Pour l'initialisation de types de données 'normaux' (comme les tableaux int), vous pouvez utiliser la notation de parenthèse, mais elle mettra à zéro les valeurs après la dernière s'il reste de l'espace dans le tableau:

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

5
2017-10-14 13:17



Une réponse un peu ironique; écrire la déclaration

array = initial_value

dans votre langage favori (le mien est Fortran, mais il y en a beaucoup d'autres), et reliez-le à votre code C. Vous voudrez probablement l'envelopper pour être une fonction externe.


5
2017-10-14 10:33



Si le tableau se trouve être int ou quelque chose avec la taille de int ou la taille de votre mem-pattern correspond à des temps exacts dans un int (c'est-à-dire tous les zéros ou 0xA5A5A5A5), la meilleure façon est d'utiliser memset ().

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


4
2017-07-29 00:17