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:
- en utilisant
malloc
, Créez un tableau dynamique de longueur10
, contenant des valeurs de typedouble
. - définissez chaque entrée du tableau sur
j/100
pourj = 0, 1,..., 9
. Ensuite l'imprimer. - ajoutez une entrée vide supplémentaire à la fin du tableau en utilisant
realloc
. - 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
Est-ce que je code ce droit?
-
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?
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.
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.
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);