Tableau dynamique en C - ma compréhension de malloc et realloc est-elle correcte?

J'apprends à créer des tableaux 1D dynamiques en C. Le code ci-dessous essaie de faire ce qui suit:

  1. en utilisant malloc, Créez un tableau dynamique de longueur 10, contenant des valeurs de type double.
  2. définissez chaque entrée du tableau sur j/100 pour j = 0, 1,..., 9. Ensuite l'imprimer.
  3. ajoutez une entrée vide supplémentaire à la fin du tableau en utilisant realloc.
  4. définissez la nouvelle entrée sur j/100 et imprimez chaque entrée Encore une fois.

Test:

 double* data = (double*)malloc(10*sizeof(double));

 for (j=0;j<10;j++)
 {
      data[j]= ((double)j)/100;
      printf("%g, ",data[j]);
 }

 printf("n");

 data = (double*)realloc(data,11*sizeof(double));

 for (j=0;j<11;j++)
 {
     if (j == 10){ data[j]= ((double)j)/100; }
     printf("%g, ",data[j]);
 }

 free((void*) data);

Questions

  1. Est-ce que je code ce droit?

  2. Tutoriels j'ai trouvé utiliser malloc sans mettre le (double*) en face. Par exemple,

    Int * pointeur;
    pointeur = malloc(2*sizeof(int));

Cela ne compile pas pour moi sur Visual Studio 2010, Windows 7. Le message d'erreur est

La valeur de type void ne peut pas être affectée à l'entité de type int.

Pourquoi ça marche pour ces tutoriels et pas pour moi? Ai-je raison de deviner que c'est parce que les compilateurs qu'ils utilisent remplissent automatiquement le (int*) pour eux dans mon exemple?

27
demandé sur Nemo 2012-10-01 19:06:43

3 réponses

Tu es proche.

En C (au moins depuis la version 1989 de la norme), la conversion avant malloc et realloc est inutile, car C peut convertir des valeurs de type void * en int * sans conversion. Ceci est Pas vrai pour C++, donc en fonction de l'erreur que vous obtenez, il semble que vous compilez ce code en C++ et non en C. Vérifiez la documentation de VS2010 pour déterminer comment compiler le code en tant que C.

Ce qui suit est mon style préféré pour écrire un malloc appel:

double *data = malloc(10 * sizeof *data);

, Puisque le type de l'expression *data est double, sizeof *data est équivalent à sizeof (double). Cela signifie également que vous n'avez pas besoin d'ajuster vos appels malloc si le type de data change.

Quant à l'appel realloc, il est plus sûr d'attribuer le résultat à une valeur de pointeur temporaire. {[3] } retournera NULL s'il ne peut pas étendre le tampon, il est donc plus sûr d'écrire

double *tmp;
...
tmp = realloc(data, 11 * sizeof *data);
if (!tmp)
{
  // could not resize data; handle as appropriate
}
else
{
  data = tmp;
  // process extended buffer
}

Sachez que le support de Microsoft pour C se termine par la version 1989 de la langue; il y a eu deux révisions de la norme linguistique depuis lors, qui ont introduit quelques nouvelles fonctionnalités et anciennes obsolètes. Ainsi, alors que certains compilateurs C prennent en charge les fonctionnalités C99 comme les déclarations mixtes et le code, les tableaux de longueur variable, etc., VS2010 ne sera pas.

34
répondu John Bode 2012-10-01 15:18:18

1) est-ce que je code ce droit?

Surtout. Mais data = (double*)realloc(data,11*sizeof(double)); perd la référence à la mémoire allouée si realloc échoue, vous devez utiliser un pointeur temporaire pour contenir la valeur de retour de realloc et vérifier si c'est NULL (et vous devez aussi vérifier la valeur de retour de malloc).

2) les tutoriels que j'ai trouvés utilisent malloc sans mettre le (double*) en face.

En C, malloc renvoie un {[6] } qui peut implicitement être converti en n'importe quel autre type de pointeur, donc non cast est nécessaire (et largement déconseillé car casting qui peut cacher les erreurs). Visual Studio compile apparemment le code en C++ où la distribution est requise.

12
répondu Daniel Fischer 2012-10-01 15:11:18

En C, vous ne devez pas convertir la valeur de retour de malloc().

En outre, c'est une mauvaise idée d'encoder le type dans l'argument malloc(). C'est une meilleure façon:

double* data = malloc(10 * sizeof *data);
5
répondu unwind 2012-10-01 15:09:25