0
votes

renvoyant la chaîne d'une fonction mais affiche null, quelle est la raison?

J'essaye de renvoyer une chaîne de la fonction str mais elle imprime (null)

#include<stdio.h>
char* str()
{
    char hi[10] = "return this";
    return hi;
}

void main()
{
    printf("%s", str());

}


1 commentaires

Puisque hi est dans la portée de str , il n'a pas de sens de renvoyer son adresse hors de la portée.


4 Réponses :


-2
votes
#include<stdio.h>
#include<stdlib.h>
char* str(){
    //malloc is used to allocate memory
    char *hi=(char*)malloc(sizeof(char)*20);
    char ch[]="return this\0";
    for(int i=0;i<sizeof(ch);i++)
    hi[i]=ch[i];
    return hi;
} 
int main(){
    printf("%s", str());
    return 0;
}
you can find more about malloc and sizeof operator.

3 commentaires

Votre portée de variable hi était limitée à la str function Ainsi, lorsque l'exécution sort de la fonction str, la pile est effacée et ainsi la mémoire allouée pour hi est également effacée car elle provoquait une erreur de segmentation.


Yuk. Il suffit de remplacer un problème par un autre (une fuite de mémoire). De plus, sizeof(char) est 1 par définition, donc sizeof(char)*20 n'a aucun avantage sur seulement 20 ici.


Votre commentaire sur votre propre réponse fait partie de la réponse et devrait apparaître dans la réponse. Le simple fait de jeter du code sans explication n'est pas vraiment une réponse à la question, même si c'est une solution au problème.



0
votes

Dans GCC au moins, votre code se compile avec les avertissements suivants:

char* str( char* str, int maxlen )
{
    str[maxlen] = '\0' ;
    return strncpy( str, "return this", maxlen - 1 ) ;
}

void main()
{
    char* buffer[32] ;
    printf("%s", str(buffer, sizeof(buffer));
}

Ce qui est plus ou moins une réponse directe à votre question. Si vous n'avez pas reçu ces avertissements, considérez le compilateur commuté que vous utilisez, pour GCC, je suggère au moins -Wall -Werror - qui affichera les avertissements les plus utiles sans être pédant, et fera ces erreurs d'avertissement donc empêchera la compilation réussie jusqu'à ce que vous répare les.

Vous renvoyez un pointeur vers une variable locale automatique qui n'est plus dans la portée après le retour de la fonction, le résultat n'est donc pas défini. Vous avez également essayé d'initialiser un tableau avec plus de caractères que vous avez réservés.

Ce que le compilateur a fait ici reçoit l'initialiseur invalide, il a défini l'adresse de hi sur null et printf gère le pointeur nul en imprimant (null) . C'est un comportement spécifique à votre compilateur et à votre bibliothèque C - dans d'autres cas, quelque chose de différent peut se produire. Plus insidieux que cela est que si votre initialiseur n'était pas invalide (en étant plus court), il est susceptible d'avoir semblé fonctionner et vous n'auriez peut-être jamais posé la question, mais ce serait toujours incorrect, et dans un code plus complexe serait probablement à certains points provoquent un comportement erroné observable.

Dans ce cas particulier, vous pouvez effectuer l'une des opérations suivantes:

const char* str()
{
    static const char hi[] = "return this";
    return hi;
}
const char* str()
{
    static const char* hi = "return this";
    return hi;
}
main.c:12:19: warning: initializer-string for array of chars is too long                                                                        
main.c:13:12: warning: function returns address of local variable [-Wreturn-local-addr]  

La solution la plus appropriée (et ce qui précède n'est en aucun cas exhaustive) dépend de ce que vous voulez réellement faire, car chaque solution diffère sémantiquement, et en elle-même, cette fonction n'est guère pratique. Il faudrait un exemple concret du monde réel pour donner les meilleurs conseils.


0 commentaires

0
votes

lire des variables statiques ou des variables globales pour accéder à la variable en dehors des fonctions

il y a un débordement dans votre code, lire le buffer overflow en c

Lisez aussi Que doit retourner main () en C et C ++?

#include<stdio.h>
char* str()
{
    static char hi[] = "return this";
    return hi;
}

int main()
{
    printf("%s", str());
    return 0;
}


3 commentaires

L'initialiseur étant trop grand ne provoque pas de débordement car il est vérifié au moment de la compilation, c'est pourquoi il imprime (null) - bien que ce comportement soit toujours indéfini. Si vous raccourcissez l'initialiseur, cela peut (et dans ce cas simple est susceptible de) sembler fonctionner, mais c'est toujours faux.


pas sûr de cela, mais ce n'est toujours pas la bonne façon de le faire, non?


C'est vrai. Le comportement que j'ai décrit j'ai déterminé empiriquement à gdbonline (GCC) .. YMMV. Un compilateur mal implémenté pourrait bien déborder de la mémoire tampon.



0
votes

Le problème vient de la portée du tableau de caractères.

La solution à ce problème est de rendre l'adresse de cette variable visible pour la fonction de l'appelant!

c'est-à-dire que l'une des solutions les plus simples est d'utiliser la ligne ci-dessous dans la partie déclaration de la variable hi de votre fonction str (). ie static char hi [10] = "return th";

dans la déclaration. De cette façon, vous n'avez pas besoin de changer quoi que ce soit dans ce programme MAIS dans tout le projet, cette variable SERA visible / accessible!


3 commentaires

FYI #include <stdio.h> char * str () {static char hi [10] = "return th"; return hi; } int main () {printf ("% s", str ()); return 0; }


De quelle manière votre solution rend-elle la variable «visible / accessible» tout au long du projet? Une variable a une portée et une durée de vie , en déclarant une static locale, elle a une durée de vie égale à la durée du programme, mais elle n'est plus visible qu'une variable non statique car elle a la même portée .


Vous devez modifier la réponse pour ajouter un code explicatif, pas l'ajouter dans les commentaires. Les commentaires ne font pas partie de la réponse et ne sont certainement pas adaptés au code d'affichage.