web-dev-qa-db-fra.com

Initialisation du tableau de caractères C

Je ne suis pas sûr de ce qui sera dans le tableau de caractères après l'initialisation des manières suivantes.

1 .char buf[10] = "";
2. char buf[10] = " ";
3. char buf[10] = "a";

Pour le cas 2, je pense que buf[0] devrait être ' ', buf[1] devrait être '\0' et que de buf[2] à buf[9] constituerait un contenu aléatoire. Pour le cas 3, je pense que buf[0] devrait être 'a', buf[1] devrait être '\ 0' et que de buf[2] à buf[9] aurait un contenu aléatoire.

Est-ce exact?

Et pour le cas 1, qu’y aura-t-il dans la buf? buf[0] == '\0' et de buf[1] à buf[9] aura-t-il un contenu aléatoire?

89
lkkeepmoving

Ce n'est pas comment vous initialisez un tableau, mais pour:

  1. La première déclaration:

    char buf[10] = "";
    

    est équivalent à

    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. La deuxième déclaration:

    char buf[10] = " ";
    

    est équivalent à

    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. La troisième déclaration:

    char buf[10] = "a";
    

    est équivalent à

    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    

Comme vous pouvez le constater, aucun contenu aléatoire: s'il y a moins d'initialiseurs, le reste du tableau est initialisé avec 0. C'est le cas même si le tableau est déclaré dans une fonction.

189
ouah

Edit: OP (ou un éditeur) a remplacé silencieusement certaines des guillemets simples de la question initiale en guillemets doubles à un moment donné après avoir fourni cette réponse.

Votre code entraînera des erreurs de compilation. Votre premier fragment de code:

char buf[10] ; buf = ''

est doublement illégal. Premièrement, en C, il n’existe pas de char vide. Vous pouvez utiliser des guillemets doubles pour désigner une chaîne vide, comme avec:

char* buf = ""; 

Cela vous donnera un pointeur sur une chaîne NUL, c’est-à-dire une chaîne à un caractère ne contenant que le caractère NUL. Mais vous ne pouvez pas utiliser de guillemets simples sans rien à l'intérieur - cela n'est pas défini. Si vous devez désigner le caractère NUL, vous devez le spécifier:

char buf = '\0';

La barre oblique inverse est nécessaire pour distinguer le caractère '0'.

char buf = 0;

fait la même chose, mais le premier est un peu moins ambigu à lire, je pense.

Deuxièmement, vous ne pouvez pas initialiser les tableaux après leur définition.

char buf[10];

déclare et définit le tableau. L'identificateur de tableau buf est maintenant une adresse en mémoire et vous ne pouvez pas modifier l'emplacement où buf pointe dans l'affectation. Alors

buf =     // anything on RHS

est illégal. Vos deuxième et troisième fragments de code sont illégaux pour cette raison.

Pour initialiser un tableau, vous devez le faire au moment de la définition:

char buf [10] = ' ';

vous donnera un tableau de 10 caractères, le premier caractère étant l’espace '\040' et le reste étant NUL, c’est-à-dire '\0'. Lorsqu'un tableau est déclaré et défini avec un initialiseur, les éléments du tableau (le cas échéant) dépassant ceux avec les valeurs initiales spécifiées sont automatiquement remplis avec 0. Il n'y aura pas de "contenu aléatoire".

Si vous déclarez et définissez le tableau mais ne l'initialisez pas, comme dans l'exemple suivant:

char buf [10];

vous aurez un contenu aléatoire dans tous les éléments.

21
verbose
  1. Ce sont équivalent

    char buf[10] = "";
    char buf[10] = {0};
    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. Ce sont équivalent

    char buf[10] = " ";
    char buf[10] = {' '};
    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. Ce sont équivalent

    char buf[10] = "a";
    char buf[10] = {'a'};
    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
19
Steven Penny

La partie pertinente de l'initialisation de la version préliminaire de la norme C11 n1570 6.7.9 indique:

14 Un tableau de type caractère peut être initialisé à l'aide d'un littéral de chaîne de caractères ou d'un littéral de chaîne UTF-8, éventuellement entre crochets. Les octets successifs du littéral chaîne (y compris le caractère nul final s'il y a de la place ou si le tableau est de taille inconnue) initialisent les éléments du tableau.

et

21S'il y a moins d'initialiseurs dans une liste entre accolades qu'il n'y a d'éléments ou de membres d'un agrégat, ou moins de caractères dans un littéral utilisé pour initialiser un tableau de taille connue qu'il n'y a d'éléments dans le tableau, le reste de l'agrégat doit être initialisé implicitement de la même manière que les objets ayant une durée de stockage statique .

Ainsi, '\ 0' est ajouté, s'il y a suffisamment d'espace, et les caractères restants sont initialisés avec la valeur qu'un static char c; serait initialisé dans une fonction.

Finalement,

1 Si un objet ayant une durée de stockage automatique n'est pas initialisé explicitement, sa valeur est indéterminée. Si un objet dont la durée de stockage statique ou le thread n'est pas explicitement initialisé, alors:

[-]

  • s'il est de type arithmétique, il est initialisé à zéro (positif ou non signé);

[-]

Ainsi, char étant de type arithmétique, le reste de la matrice est également garanti pour être initialisé avec des zéros.

6
Antti Haapala

Il est intéressant de noter qu’il est possible d’initialiser les tableaux de n’importe quelle façon à n’importe quel moment du programme, à condition qu’ils soient membres d’un groupe struct ou union.

Exemple de programme:

#include <stdio.h>

struct ccont
{
  char array[32];
};

struct icont
{
  int array[32];
};

int main()
{
  int  cnt;
  char carray[32] = { 'A', 66, 6*11+1 };    // 'A', 'B', 'C', '\0', '\0', ...
  int  iarray[32] = { 67, 42, 25 };

  struct ccont cc = { 0 };
  struct icont ic = { 0 };

  /*  these don't work
  carray = { [0]=1 };           // expected expression before '{' token
  carray = { [0 ... 31]=1 };    // (likewise)
  carray = (char[32]){ [0]=3 }; // incompatible types when assigning to type 'char[32]' from type 'char *'
  iarray = (int[32]){ 1 };      // (likewise, but s/char/int/g)
  */

  // but these perfectly work...
  cc = (struct ccont){ .array='a' };        // 'a', '\0', '\0', '\0', ...
  // the following is a gcc extension, 
  cc = (struct ccont){ .array={ [0 ... 2]='a' } };  // 'a', 'a', 'a', '\0', '\0', ...
  ic = (struct icont){ .array={ 42,67 } };      // 42, 67, 0, 0, 0, ...
  // index ranges can overlap, the latter override the former
  // (no compiler warning with -Wall -Wextra)
  ic = (struct icont){ .array={ [0 ... 1]=42, [1 ... 2]=67 } }; // 42, 67, 67, 0, 0, ...

  for (cnt=0; cnt<5; cnt++)
    printf("%2d %c %2d %c\n",iarray[cnt], carray[cnt],ic.array[cnt],cc.array[cnt]);

  return 0;
}
3
user3381726

Je ne suis pas sûr, mais j'initialise généralement un tableau sur "". Dans ce cas, je n'ai pas besoin de m'inquiéter de la fin nulle de la chaîne.

main() {
    void something(char[]);
    char s[100] = "";

    something(s);
    printf("%s", s);
}

void something(char s[]) {
    // ... do something, pass the output to s
    // no need to add s[i] = '\0'; because all unused slot is already set to '\0'
}
0
Erric Rapsing