Pourquoi le premier code fonctionne bien, tandis que le second n'est pas? La seule différence est l'endroit où je place En outre, je ne reçois aucune erreur ni avertissements lors de l'exécution du deuxième code. Y a-t-il une façon de pouvoir obtenir des informations supplémentaires du compilateur pour me mener dans la bonne direction? Merci! P> NB Strong> excuses pour le code n'étant pas très organisé à partir d'un point de stand logique, il suffit de travailler pour obtenir une meilleure compréhension de quelques concepts de programmation. P > 1er code: p> 2e code: p> calloc code> dans la fonction secondaire. La raison pour laquelle je demande est que j'aurais pensé que le deuxième code est celui qui fonctionne, en considérant la valeur de
divisor_number code> est seulement connue une fois que je fais la boucle de la fonction secondaire. Pourriez-vous me donner une explication rapide sur celui-ci? Merci!
4 Réponses :
Il suffit de partir ici le code final qui fonctionne, en tenant également compte @weathervane Commentaire, et assurez-vous que divisor_number code> est initialisé.
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int* save_number(int *int_number);
int main()
{
int int_number, *divisors = 0, count_even, i;
printf("Please enter an integer:");
divisors = save_number(&int_number);
for (i = 1; i <= int_number; ++i)
{
if (divisors[i-1] % 2 == 0 && divisors[i-1] != 0)
{
printf("%d\n", divisors[i-1]);
count_even++;
}
continue;
}
printf("Total even divisors: ");
printf("%d\n", count_even);
return 0;
}
int* save_number(int *int_number)
{
int i, *divisors = 0, divisor_number = 0;
divisors = calloc(divisor_number, sizeof *divisors);
scanf("%d", int_number);
for (i = 1; i <= *int_number; ++i)
{
if (*int_number % i == 0)
{
divisors[i-1] = i;
printf("%d\n", divisors[i-1]);
divisor_number++;
}
continue;
}
return divisors;
}
faire diviseurs = calloc (divisor_number, taille de * diviseurs); code> quand
divisor_number = 0 code> Vous allouez un bloc de taille 0
Dans le premier cas, lorsque vous faites
divisors[i-1] = i;
divisor_number code> est ininitialisé dans codes i>. Dans la seconde a été incrémenté mais n'est pas moins défini.
Bon point, mais dans le second cas, le crash se passera même avant que divisor_number code> est utilisé.
Vous avez plusieurs comportements non définis dans votre code:
faire p>
calloc (divisor_number, taille de * diviseurs); p> blockquote>
tandis que
divisor_number code> n'est pas encore initialisé, puis à l'aide du bloc attribué p>
dans votre deuxième proposition alloue également le bloc après l'écriture em> en elle. p>
Si l'utilisateur ne saisit pas un entier valide, laissez
* int_number code> non initialisé. p>
Si vous ne pouvez pas affecter le bloc (indépendamment de l'UB précédent) p>
Vous pouvez facilement supprimer ces UBS. p>
Vous connaissez les éléments numériques dont vous aurez besoin pour enregistrer car c'est la valeur du numéro que vous lisez
dans le premier code remplacer P>
int i, *divisors; if ((scanf("%d", int_number) != 1) || (*int_number < 1)) { ..indicate error exit(1); } if ((divisors = calloc(*int_number, sizeof *divisors)) == NULL) { ..indicate error exit(1); } ...
Les deux versions du code ont des erreurs.
dans la première version que vous avez: p> ici, dans le deuxième code: p> à ce point Votre réponse postée ne fonctionne pas non plus car vous indiquez Vous devez utiliser la valeur lue dans divisor_number code> est non initialisé Sa valeur est
calloc code> était suffisamment grande pour allouer suffisamment de mémoire, ou que ce n'était pas assez grand et que vous n'aviez pas réussi à ne pas casser quoi que ce soit en écrivant au-delà de la fin de la mémoire allouée. p>
divisiors code> est défini Pour NULL, vous êtes donc la désérogation d'un pointeur nul qui est également un comportement indéfini. De plus, comme dans le premier code,
divisor_number code> est encore ininitialisé, vous essayez de l'incrémenter. P>
calloc < / Code> Pour allouer 0 octets de mémoire, tout accès à l'élément de la matrice alloué lit après la fin. P>
int_number code> pour allouer mémoire et appelant
calloc code> juste après le faire. C'est la quantité réelle d'espace dont vous avez besoin. p>
AVERTISSEMENT DOIT ÊTRE CALLOC (* INT_NUMBER ... CODE> Et c'est ce que je fais dans ma réponse (sur le fait que j'ai ajouté des tests pour éviter l'UB si un nombre non valide, etc.) ;-);
@bruno bonne prise. Fixé.
Les deux code sont faux, car
divisor_number code> (transmis sur
calloc code>) n'est jamais initialisé. Ils ont tous deux comportement indéfini i> et c'est une loterie qui, le cas échéant, fonctionne comme prévu. "La valeur de divisor_number n'est connue qu'une fois que j'ai fait la boucle".
divisor_number code> est jamais i> connu.
Dans la deuxième version, vous avez UB, car
diviseurs code> ne pointe pas sur la mémoire valide dans la boucle, lorsque vous l'indexez.
calloc code> attribue la mémoire, vous ne pouvez pas attribuer la mémoire après i> Vous avez déjà essayé d'utiliser ladite mémoire. Vous devez l'allouer avant.
@ Weathervane - dans le premier segment:
* diviseurs = 0 code> initialise le pointeur, puis
diviseurs = save_number (& int_number); code> retourne la mémoire allouée. Où est l'UB dans le premier segment?
" Je ne reçois pas d'erreurs ni d'avertissements lors de l'exécution du deuxième code. i>", regarde Valgrind i> pour voir les erreurs à l'exécution de Version B>
@ryyker dans les deux sections, fonction
sauvegarde_number () code> définit
int divisor_number code> qui dans un cas est immédiatement transmis à
calloc code> et dans l'autre cas est incrémenté. Avant Ditto. Nulle part a été une valeur fixée.