111 votes

Initialisation d'un tableau 2D entier avec une seule valeur

Avec la déclaration suivante

int array[ROW][COLUMN]={0};

J'obtiens le tableau avec tous les zéros mais avec le suivant

int array[ROW][COLUMN]={1};

Je n'obtiens pas le tableau avec une seule valeur. La valeur par défaut est toujours 0.

Pourquoi ce comportement et comment puis-je initialiser avec tous les 1 ?

EDIT : Je viens de comprendre qu'en utilisant memset avec une valeur de 1, définira chaque octet comme 1 et donc la valeur réelle de chaque cellule du tableau ne sera pas 1 mais 16843009 . Comment puis-je le régler sur 1 ?

154voto

Lundin Points 21616

Vous obtenez ce comportement, parce que int array [ROW][COLUMN] = {1}; fait pas signifie "mettre tous les éléments à un". Je vais essayer d'expliquer comment cela fonctionne, étape par étape.

La manière explicite et trop claire d'initialiser votre tableau serait la suivante :

#define ROW 2
#define COLUMN 2

int array [ROW][COLUMN] =
{
  {0, 0},
  {0, 0}
};

Cependant, le C vous permet de laisser de côté certains éléments d'un tableau (ou d'une structure/union). Vous pourriez par exemple écrire :

int array [ROW][COLUMN] =
{
  {1, 2}
};

Cela signifie qu'il faut initialiser les premiers éléments à 1 et 2, et le reste des éléments "comme s'ils avaient une durée de stockage statique". Il y a une règle en C qui dit que tous les objets de durée de stockage statique, qui ne sont pas explicitement initialisés par le programmeur, doivent être mis à zéro.

Ainsi, dans l'exemple ci-dessus, la première ligne prend la valeur 1,2 et la suivante la valeur 0,0 puisque nous ne leur avons pas donné de valeurs explicites.

Ensuite, il existe une règle en C qui autorise un style d'accolade plus souple. Le premier exemple pourrait aussi bien être écrit comme

int array [ROW][COLUMN] = {0, 0, 0, 0};

bien qu'il s'agisse bien sûr d'un style pauvre, plus difficile à lire et à comprendre. Mais cette règle est pratique, car elle nous permet d'écrire

int array [ROW][COLUMN] = {0};

ce qui signifie : "initialiser la toute première colonne de la première ligne à 0, et tous les autres éléments comme s'ils avaient une durée de stockage statique, c'est-à-dire les mettre à zéro".

par conséquent, si vous tentez

int array [ROW][COLUMN] = {1};

cela signifie "initialiser la toute première colonne de la première ligne à 1 et mettre tous les autres éléments à zéro".

55voto

user2021512 Points 486

Si vous voulez initialiser le tableau à -1 alors vous pouvez utiliser ce qui suit,

memset(array, -1, sizeof(array[0][0]) * row * count)

Mais cela va fonctionner 0 y -1 seulement

15voto

teppic Points 4715
int array[ROW][COLUMN]={1};

Ceci n'initialise que le premièrement élément à 1. Tout le reste reçoit un 0.

Dans le premier cas, vous faites la même chose - initialiser le premier élément à 0, et le reste par défaut à 0.

La raison est simple : pour un tableau, le compilateur initialisera chaque valeur que vous ne spécifiez pas avec 0.

Avec un char vous pouvez utiliser memset pour définir chaque octet, mais cela ne fonctionnera généralement pas avec un fichier int (bien que cela convienne pour 0).

Un général for loop le fera rapidement :

for (int i = 0; i < ROW; i++)
  for (int j = 0; j < COLUMN; j++)
    array[i][j] = 1;

Ou peut-être plus rapide (selon le compilateur)

for (int i = 0; i < ROW*COLUMN; i++)
  *((int*)a + i) = 1;

12voto

Gaurav Suthar Points 111

Pour initialiser un tableau 2d avec zéro, utilisez la méthode ci-dessous : int arr[n][m] = {};

NOTA : La méthode ci-dessus ne fonctionnera que pour initialiser avec 0 ;

10voto

Jonathan Leffler Points 299946

Notez que GCC dispose d'une extension de l'option initialisateur désigné qui est très utile pour le contexte. Elle est également autorisée par clang sans commentaire (en partie parce qu'il essaie d'être compatible avec GCC).

La notation d'extension vous permet d'utiliser ... pour désigner une plage d'éléments à initialiser avec la valeur suivante. Par exemple :

#include <stdio.h>

enum { ROW = 5, COLUMN = 10 };

int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = 1 } };

int main(void)
{
    for (int i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COLUMN; j++)
            printf("%2d", array[i][j]);
        putchar('\n');
    }
    return 0;
}

Le résultat est, sans surprise :

 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1

Notez que Fortran 66 (Fortran IV) avait des comptes de répétition pour les initialisateurs de tableaux ; j'ai toujours trouvé étrange que le C ne les ait pas obtenus lorsque les initialisateurs désignés ont été ajoutés au langage. Et Pascal utilise le 0..9 pour désigner l'intervalle de 0 à 9 inclus, mais le C n'utilise pas la notation .. comme un jeton, il n'est donc pas surprenant qu'il n'ait pas été utilisé.

Notez que les espaces autour des ... sont essentiellement obligatoires ; s'ils sont attachés à des nombres, ceux-ci sont interprétés comme des nombres à virgule flottante. Par exemple, 0...9 serait symbolisé par 0. , . , .9 et les nombres à virgule flottante ne sont pas autorisés comme indices de tableau. Avec les constantes nommées, ...ROW-1 ne causerait pas de problèmes, mais il est préférable de prendre des habitudes sûres.


Addenda :

Je note au passage que GCC 7.3.0 rejette :

int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = { 1 } } };

où il y a un ensemble supplémentaire d'accolades autour de l'initialisateur scalaire 1 ( error: braces around scalar initializer [-Werror] ). Je ne suis pas sûr que ce soit correct étant donné que vous pouvez normalement spécifier des accolades autour d'un scalaire en int a = { 1 }; ce qui est explicitement autorisé par la norme. Je ne suis pas non plus certain que ce soit incorrect.

Je me demande également si une meilleure notation ne serait pas [0]...[9] - qui n'est pas ambiguë, ne peut être confondue avec aucune autre syntaxe valide et évite toute confusion avec les nombres à virgule flottante.

int array[ROW][COLUMN] = { [0]...[4] = { [0]...[9] = 1 } };

Peut-être que le comité des normes pourrait y réfléchir ?

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