web-dev-qa-db-fra.com

Comment initialiser tous les membres d'un tableau avec 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 déjà connu un moyen simple de faire cela. 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?

855
Matt

Sauf si cette valeur est 0 (dans ce 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, cela initialisera tous les éléments sur 0:

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

En C++, une liste d'initialisation vide initialisera également chaque élément sur 0 . Ceci est non autorisé 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 initiateur n'est spécifié:

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

Et ce "0" ne veut pas nécessairement dire "tout-bits-zéro", utiliser ce qui précède est donc meilleur et plus portable que memset (). (Les valeurs en virgule flottante seront Initialisées à +0, les pointeurs sur une valeur nulle, etc.)

1116
aib

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

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

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

364
qrdl

Pour initialiser de manière statique 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 modifier 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. 

169
mouviciel

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

61
Frank Szczerba

J'ai vu du code qui utilisait cette syntaxe:

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

Cela devient particulièrement utile si vous créez 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 enum dans le désordre.

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

47
abelenky
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 cas la taille du tableau change.

21
Tarski

Vous pouvez faire tout l'initialisation statique comme décrit ci-dessus, mais cela peut être une véritable perte de temps 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 déchets).

memset vous donne un coup au moteur d’exécution pour effectuer le travail, mais aucun coup de taille de code effectué correctement n’est à l’abri des changements de taille de 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é de manière statique, j'écrirais un programme pour écrire le programme pour moi et l'intégrer au processus de construction.

11
plinth

Voici un autre moyen:

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:

Extensions C

Inits désignés

Puis posez la question suivante: quand peut-on utiliser des 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. 

7
humble_guru

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

array = initial_value

dans votre langage favori compatible avec les tableaux (le mien est Fortran, mais il y en a beaucoup d'autres), et le lier à votre code C. Vous voudrez probablement en faire une fonction externe.

5

Pour initialiser des types de données «normaux» (comme les tableaux int), vous pouvez utiliser la notation entre crochets, mais les valeurs après le dernier seront remises à zéro 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
warren

Si le tableau est int ou quoi que ce soit avec la taille int ou la taille de votre modèle meme correspond aux temps exacts dans un int (c'est-à-dire tous les zéros ou 0xA5A5A5A5), le meilleur moyen est d'utiliser memset () .

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

4
ddimitrov
  1. Si votre tableau est déclaré statique ou global, tous les élémentsdans le tableau ont déjà la valeur par défaut 0.
  2. Certains compilateurs définissent la valeur par défaut de array sur 0 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 d’autres valeurs, vous devez utiliser memset () ou loop;

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

1
Hannah Zhang

En réponse à toutes les discussions, 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 supplémentaire: le code est réellement lisible :)

1
JWDN

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

#include <iostream>

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:

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
1
hkBattousai

Pour l’initialisation retardée (initialisation du constructeur du membre de la classe), prenez en compte:

int a[4];

unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
  a[i] = 0;
0
nikc
#include<stdio.h>
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 d'un tableau entier

0
Dadhich Sourav

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


Si vous connaissez la taille du tableau à l'avance ...

#include <stdio.h>

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 que UINT myArray[size]; n'est pas directement initialisé lors de la déclaration, mais le bloc de code ou l'appel de fonction suivant initialise chaque élément du tableau avec la même valeur que vous le souhaitez. L'autre inconvénient est que vous devez écrire un initializing function pour chaque type que vous prendrez en charge et vous devez également modifier la fonction printArray() pour prendre en charge ces types.


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

0
Francis Cugler