55 votes

Déclaration et initialisation de tableaux en C

Existe-t-il un moyen de déclarer d'abord puis d'initialiser un tableau en C?

Jusqu'à présent, j'ai initialisé un tableau comme celui-ci:

 int myArray[SIZE] = {1,2,3,4....};
 

Mais j'ai besoin de faire quelque chose comme ça

 int myArray[SIZE];

myArray = {1,2,3,4....};
 

33voto

AndreyT Points 139512

En C99, vous pouvez le faire en utilisant un littéral composé en combinaison avec memcpy

 memcpy(myarray, (int[]) { 1, 2, 3, 4 }, sizeof myarray);
 

(en supposant que la taille de la source et la taille de la cible sont les mêmes).

Dans C89 / 90, vous pouvez émuler cela en déclarant un tableau "source" supplémentaire

 const int SOURCE[SIZE] = { 1, 2, 3, 4 }; /* maybe `static`? */
int myArray[SIZE];
...
memcpy(myarray, SOURCE, sizeof myarray);
 

14voto

paxdiablo Points 341644

Non, vous ne pouvez pas les mettre à des valeurs arbitraires dans un énoncé (à moins de faire partie de la déclaration).

Vous pouvez soit le faire avec du code, quelque chose comme:

myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 27;
:
myArray[99] = -7;

ou (si il y a une formule):

for (int i = 0; i < 100; i++) myArray[i] = i + 1;

L'autre possibilité est de garder autour de quelques modèles qui sont fixés au moment de la déclaration et de les utiliser pour initialiser ton tableau, quelque chose comme:

static const int onceArr[]  = {  0,  1,  2,  3,  4,..., 99};
static const int twiceArr[] = {  0,  2,  4,  6,  8,...,198};
:
int myArray[7];
:
memcpy (myArray, twiceArr, sizeof (myArray));

Cela a l'avantage d' (le plus probable) en étant plus rapide et permet de créer des petits tableaux que les modèles. J'ai utilisé cette méthode dans des situations où je dois ré-initialiser un tableau rapide, mais à un état spécifique (si l'état étaient tous les zéros, je voudrais juste utiliser memset).


Vous pouvez même localiser l'endroit d'une phase d'initialisation de la fonction:

void initMyArray (int *arr, size_t sz) {
    static const int template[] = {2, 3, 5, 7, 11, 13, 17, 19, 21, ..., 9973};
    memcpy (arr, template, sz);
}
:
int myArray[100];
initMyArray (myArray, sizeof(myArray));

Le tableau statique sera (presque certainement) être créé au moment de la compilation, donc il n'y aura pas de course coût pour, et l' memcpy doit être absolument rapidement, bien plus vite que 1,229 les instructions d'affectation :-).

4voto

Jacob Points 793

Existe-t-il un moyen de déclarer d'abord puis d'initialiser un tableau en C?

Il y a! mais sans utiliser la méthode que vous avez décrite.

Vous ne pouvez pas initialiser avec une liste séparée par des virgules, cela n’est autorisé que dans la déclaration. Vous pouvez cependant initialiser avec ...

 myArray[0] = 1;
myArray[1] = 2;
...
 

ou

 for(int i = 1; i <= SIZE; i++)
{
  myArray[i-1] = i;
}
 

2voto

Joseph Quinsey Points 4450

Ce document est un addendum à la accepté de répondre par AndreyT, avec Nyan commentaire incompatibles tableau des tailles. Je suis en désaccord avec leur réglage automatique de la cinquième élément à zéro. Il devrait être 5 --le nombre après 1,2,3,4. Je vous suggère un wrapper de memcpy() pour produire une compilation d'erreur quand on essaie de copier des tableaux de tailles différentes:

#define Memcpy(a,b) do {                    /* copy arrays */       \
    ASSERT(sizeof(a) == sizeof(b) &&        /* a static assert */   \
           sizeof(a) != sizeof((a) + 0));   /* no pointers */       \
    memcpy((a), (b), sizeof (b));           /* & unnecesary */      \
    } while (0)                             /* no return value */

Cette macro génère une erreur de compilation si votre tableau est de longueur 1. Ce qui est peut-être une fonction.

Parce que nous sommes l'aide d'une macro, le C99 littéral composé semble avoir besoin d'une paire de parenthèses:

Memcpy(myarray, ((int[]) { 1, 2, 3, 4 }));

Ici ASSERT() est un "statique affirmer'. Si vous n'avez pas déjà votre propre, j'utilise la suite sur un certain nombre de plates-formes:

#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) /* version of ASSERT() with message */ \
    enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}

1voto

Jonathan Leffler Points 299946

Pourquoi ne pouvez-vous pas initialiser lorsque vous déclarez?

Qui C compilateur que vous utilisez? Prend-il en charge du C99?

Si elle prend en charge la C99, vous pouvez déclarer la variable dans laquelle vous en avez besoin et l'initialiser lorsque vous déclarez.

La seule excuse que je peux penser pour ne pas faire ce serait parce que vous avez besoin de le déclarer, mais faire une petite sortie avant de l'utiliser, de sorte que l'initialiseur, serait perdu. Cependant, je soupçonne qu'un tel code n'est pas aussi proprement organisé comme il se doit et peut être écrite, de sorte qu'il n'était pas un problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X