Comment initialiser tous les membres d'un tableau de 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 de la même valeur. Je pourrais jurer que j'ai connu une façon simple de faire ça. 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?
18 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 manière facile.
N'oubliez 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++, Un vide liste d'initialisation va également initialiser chaque élément à 0. C'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 s'initialiseront à 0 si non l'initialiseur est spécifié:
static int myArray[10]; // all elements 0
et que "0" ne signifie pas nécessairement "tous-bits-zéro", donc en utilisant ce qui précède est meilleur et plus portable que memset (). (Les valeurs en virgule flottante seront initialisé à +0, pointeurs vers la valeur nulle, etc.)
si votre compilateur est GCC, vous pouvez utiliser la syntaxe suivante:
int array[1024] = {[0 ... 1023] = 5};
vérifier la description détaillée: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
pour l'initialisation statique d'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 avez besoin de changer la valeur, vous devez faire le remplacement à un seul endroit.
modifier: extensions utiles possibles
(gracieuseté de Jonathan Leffler )
vous pouvez facilement généraliser 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 matrices composées.
#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 macros sont négociables.
si vous voulez vous assurer que chaque membre du tableau est explicitement initialisé, il suffit d'omettre 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 extérieure 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 un code qui utilisait cette syntaxe:
char* array[] =
{
[0] = "Hello",
[1] = "World"
};
où il 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 maintient les choses en ordre, même si vous vous trouvez à écrire certaines des valeurs enum hors de l'ordre.
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...
incrase la taille du tableau change.
vous pouvez faire toute la chose static initializer comme détaillé ci-dessus, mais il peut être un vrai déception lorsque la taille de votre tableau change (lorsque votre tableau embiggens, si vous n'ajoutez pas les initialisateurs supplémentaires appropriés vous obtenez des ordures).
memset vous donne un hit runtime pour faire le travail, mais aucun hit de taille de code fait correctement est immunisé aux changements de taille de tableau. J'utiliserais cette solution dans presque tous les cas où le tableau était plus grand que, disons, quelques douzaines d'éléments.
S'il était vraiment important que le tableau soit statiquement déclaré, j'écrirais un programme pour écrire le programme pour moi et le faire partie du 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:
désignés inits
posez alors la question: Quand peut-on utiliser les extensions C?
l'échantillon 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' normales '(comme les tableaux int), vous pouvez utiliser la notation bracket, mais elle mettra à zéro les valeurs après la dernière si 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};
Un peu la langue-dans-joue réponse; écrire l'instruction
array = initial_value
dans votre langage favori (le mien est Fortran, mais il y en a beaucoup d'autres), et liez-le à votre code C. Vous voudriez probablement l'emballer pour une fonction externe.
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 (i.e. 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.
il y a un moyen rapide d'initialiser le tableau de n'importe quel type avec la valeur donnée. Il fonctionne très bien avec les grands tableaux. L'algorithme est le suivant:
- initialiser le premier élément du tableau (de la manière habituelle)
- partie de copie qui a été réglée en partie qui n'a pas été réglée, doublant la taille à chaque opération de copie suivante
pour 1 000 000
elements int
array c'est 4 temps plus rapides que l'initialisation de boucle régulière (i5, 2 cœurs, 2,3 GHz, Mémoire 4GiB, 64 bits):
loop runtime 0.004248 [seconds]
memfill() runtime 0.001085 [seconds]
#include <stdio.h>
#include <time.h>
#include <string.h>
#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 servira d'exemple.
#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
- si votre tableau est déclaré statique ou global, tous les éléments dans le tableau ont déjà la valeur par défaut 0.
- certains compilateurs ont défini le tableau par défaut à 0 en mode de débogage.
- il est facile de définir la valeur par défaut à 0 : tableau int[10] = {0};
- Cependant, pour d'autres valeurs, vous devez utiliser memset() ou loop;
exemple: tableau int[10]; memset(tableau,-1, 10 * sizeof(int));
coupant à travers 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 en fait lisible :)
#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 l'o / p 5 5 5 5 5 5 ...... jusqu'à la taille de l'ensemble du tableau
je sais que l'utilisateur Tarski
a répondu à cette question d'une manière similaire, mais j'ai ajouté quelques détails. Je suis un peu rouillé car je suis plus enclin à vouloir UTILISER C++, mais c'est parti.
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'une est que UINT myArray[size];
n'est pas directement initialisé sur la déclaration, cependant le très le prochain appel de bloc de code ou de fonction initialise chaque élément du tableau à la même valeur que vous voulez. L'autre mise en garde est, vous devrez écrire un initializing function
pour chaque type
que vous supporterez et vous devrez aussi modifier la fonction printArray()
pour supporter ces types.
vous pouvez essayer ce code avec un complier en ligne trouvé ici .
Je ne vois aucune exigence dans la question, de sorte que la solution doit être générique: initialisation d'un ensemble éventuellement multidimensionnel non spécifié construit à partir d'éléments éventuellement de structure non spécifiés avec une valeur initiale de membre:
#include <string.h>
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 <stdio.h>
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