0
votes

Pourquoi le tableau de caractères est vide en C

Mon code comme suit:

char* int2str(int val);

void main(){
 char *s = int2str(1001);
 printf("----s=%s\n",s);
}

char* int2str(int val){
  char turnStr[10];
  sprintf(turnStr, "%d", val);
  //printf("turnStr=%s\n",turnStr);
  return turnStr;
}


7 commentaires

Votre wrapper autour de sprintf s'avère être une responsabilité énorme ici. Il suffit d'utiliser sprintf directement si vous devez ou printf à la place.


Incroyable que les gens ne lisent pas bien la question. Votre question était "pourquoi a fait Ça fonctionnait?" Et Everone a-t-il répondu "Pourquoi n'a-t-il pas fonctionné?".


@Davidg. Cela dépend de votre définition de "travail"


@ M. Dans ce cas, émettez la lecture de la ligne "---- S = 1001" est "travail". Il a demandé pourquoi cela est sorti au lieu de, dans un cas de mien, avec C échappé ajouté, "----- S = \ x98 \ x06 @"


Ceci (pourquoi cela fonctionnait-il) est l'une des FAQ les plus courantes sous la balise C, pourtant 5 personnes post des réponses ... Certaines réponses ne répondent même même pas à la question. Pour ceux qui ignorent, nous avons une collection d'objectifs de dupe canonique que vous pouvez utiliser / devoir utiliser dans ces cas. Consultez le C Tag wiki , faites défiler jusqu'à FAQ.


@Lundin personnellement, je ne pense pas que la question que vous avez référencée est un bon match. Cette question n'est probablement pas susceptible de donner à aucun autre résultat (à l'exception d'un compilateur récent qui nule la valeur de retour). Il n'y a pas de solution qui écrase les données dans ce cas. Cela pourrait être plus proche si les données avaient été émises à plusieurs reprises sans la réinitialiser. Le fait que ce soit C ++ n'aide pas. Cette affaire demandait pourquoi cela a fonctionné parfois et pas d'autres.


@Davidg. C'est un match parfait pour les personnes qui essaient de "prouver" comment leur code de comportement indéfini est lié à la portée "Works". Mieux avec une analogie que de les clobber avec un "quel est le comportement indéfini". En tout cas, cela a été posé de milliers de fois auparavant. N'hésitez pas à creuser d'autres doubles doublons, il devrait y avoir beaucoup.


5 Réponses :


1
votes

Vous retournez une référence à la variable locale Char Trifftr [10] . Lorsque la fonction est sortie, la mémoire utilisée par cette référence est nettoyée. Donc, dans Main () Vous êtes laissé avec un pointeur pendling: char * s pointe vers la mémoire qui n'est plus valide.


2 commentaires

Non, vous pouvez retourner un objet de stockage automatique. Vous devriez (parce que vous pouvez bien sûr) ne pas renvoyer la référence référence à cet objet. int foo (vide) {int A = 5; retourner A;} va bien. int * foo (vide) {int A = 5; retour & a;} n'est pas.


Ne répond pas à la question "Il a été capable d'imprimer la bonne chaîne. Je savais que l'espace de pile ne peut pas retourner lorsque la fonction était terminée, mais je suis confus lorsque j'ai ajouté Printf (" Turnstr =% s \ n " , Turnstr), il pourrait imprimer la chaîne. "



1
votes

Le tableau Char est stocké sur le cadre de pile de la fonction int2tr . Cela signifie que si la fonction est toujours en cours d'exécution, la mémoire de la pile est stable et utilisable. C'est pourquoi vous pouvez imprimer la chaîne. Toutefois, une fois que vous êtes revenu de la fonction, rien ne garantit que la mémoire sera maintenue et qu'elle peut être effacée ou réutilisée comme vous avez été témoin.


1 commentaires

Il peut être stocké, mais il n'est pas nécessaire que la norme C ne sache rien sur la pile. Peu importe où les objets de stockage automatiques ne sont stockés que leur champ d'application



0
votes

Référence de retour (pointeur) sur l'objet local est un comportement non défini. De nombreux compilateurs modernes émettent l'avertissement et attribuent ce pointeur avec le null - par exemple GCC. Un autre problème que vous avez avec ce code est un autre UB. Votre tableau de caractères n'est pas assez long pour accueillir la chaîne

Comment régler le trier (un exemple): xxx

https://godbolt.org/z/f3cx3e


0 commentaires

0
votes

Pour commencer Selon la standard C, la fonction principale code> sans paramètres doit être déclarée comme xxx pré>

qui est son type de retour doit être int Code>. P>

Votre programme a un comportement non défini car le pointeur retourné de la fonction int2tr code> pointe vers un tableau local avec la durée de stockage automatique qui ne sera pas en vie après la sortie de la fonction. Donc, le pointeur aura une valeur non valide. La mémoire occupée par le tableau local peut être écrasée par un appel de toute autre fonction (par exemple par un appel de printf code> dans MAIN). P>

Vous devez donc allouer une mémoire dynamique pour la chaîne de destination. Pour utiliser un tableau local avec une durée de stockage statique dans la fonction n'est pas une bonne idée car appeler la fonction plusieurs fois mènera que les chaînes de résultat précédentes seront écrasées. P>

Faites attention à cela, par exemple la valeur de int_min code> (l'utilisateur de la fonction peut passer toute valeur entière valide) peut être égale à -2147483648 code> qui nécessite une matrice de caractères de 12 code> la chaîne qui représente un tel nombre. p>

Pour calculer la taille requise de la chaîne, vous pouvez utiliser un appel de la fonction C snaprintf code> avec le deuxième argument égal à 0 code>. p>

Voici un programme de démonstration. P>

1001


2 commentaires

C'est un moyen intelligent de trouver les octets dont vous avez besoin pour stocker un numéro entier, mais ce n'est pas portable. Voir les notes de snaprintf () , "La mise en œuvre de la glibc des fonctions SNPRINTF () et VSNPRINTF () est conforme à la norme C99, c'est-à-dire comme décrit ci-dessus, puisque GlibC version 2.1. Jusqu'à glibc 2.0.6, ils retourneraient -1 lorsque la sortie a été tronquée. "


"... Selon la norme C, la fonction principale sans paramètres doit être déclarée ..." C'est selon l'environnement Environnement hébergé Sous-Chapitre des environnements d'exécution. Les formes définies par la mise en œuvre des principaux () sont autorisées, par exemple, tous les systèmes de freestanding utilisent des formes de main-même définies par la mise en œuvre (), où void principal (void) est le plus courant. Voir Ceci .



1
votes

Merveilleux!

Le problème de base est que vous avez renvoyé l'adresse de quelque chose sur la pile et cela a été changé par autre chose. J'ai essayé un CGC récent et je n'ai même pas retourné le pointeur de la pile, j'ai donc essayé GCC 4.4.5 et reproduit votre comportement. P>

J'ai essayé de changer de rôle principal pour: P>

void main(){
 char *s = int2str(1001);
 printf("----s=%s\n",s);
 s = int2str(1002);
 printf("----s=%s\n",s);
}


0 commentaires