2013-02-05 5 views
1

Je suis désolé de ne pouvoir supporter ma question avec du code (je n'ai pas compris comment le structurer pour qu'il soit accepté ici), mais j'essaye quand même. Si je comprends bien, une structure qui fait référence à une structure de même type devrait le faire avec un pointeur contenu pour référence. Ce pointeur peut-il faire référence à l'espace alloué sur la pile (au lieu du tas) sans créer de défaut de segmentation? -Pointeurs à empiler

Comment cela devrait-il être déclaré?

+0

Il n'y a rien de spécial que vous devez faire lorsque vous déclarez. Si un pointeur va pointer sur stack, heap ou NULL n'a aucun effet sur la façon dont une structure le contenant est déclarée. –

Répondre

0

Oui, vous pouvez utiliser des pointeurs vers des variables sur la pile, mais seulement quand la méthode qui prévoit que cadre de pile n'a pas retourné. Par exemple, cela fonctionnera:

typedef struct 
{ 
    int a; 
    float b; 
} s; 

void printStruct(const s *s) 
{ 
    printf("a=%d, b=%f\n", s->a, s->b); 
} 

void test() 
{ 
    s s; 
    s.a = 12; 
    s.b = 34.5f; 
    printStruct(&s); 
} 

Cela entraînera une erreur cependant que le cadre de pile aurait disparu:

s *bad() 
{ 
    s s; 
    s.a = 12; 
    s.b = 34.5f; 
    return &s; 
} 

EDIT: Eh bien, je dis cela provoquera une erreur, mais en appelant ce code avec:

int main() 
{ 
    test(); 
    s *s = bad(); 
    printStruct(s); 
    return 0; 
} 

Je reçois un avertissement lors de la compilation:

s.c:27:5: warning: function returns address of local variable [enabled by default] 

et le programme semble bien fonctionner:

$ ./s 
a=12, b=34.500000 
a=12, b=34.500000 

Mais il est, en fait, cassé.

+0

merci pour votre réponse. Je crois que je comprends pourquoi il devrait être brisé - mais pourquoi ça marche encore? – stian

+0

Cela est probablement dû au fait que la pile n'a pas été * réutilisée * depuis que la fonction est revenue et que tout ce qui existait auparavant est toujours valide. Si d'autres fonctions (avec des variables de pile) étaient appelées entre-temps, elles échoueraient certainement. – trojanfoe

0

Vous ne dites pas la langue que vous travaillez, donc en supposant C pour l'instant du libellé de votre question ... le code suivant est parfaitement valide:

typedef struct str_t_tag { 
    int foo; 
    int bar; 
    struct str_t_tag *pNext; 
} str_t; 

str_t str1; 
str_t str2; 
str1.pNext = &str2; 

Dans cet exemple, les deux str1 et str2 sont sur la pile, mais cela fonctionnerait également si l'un ou les deux étaient sur le tas. La seule chose dont vous devez faire attention est que les variables de la pile seront zappées lorsqu'elles sont hors de portée, donc si vous aviez dynamiquement alloué str1 et que vous l'avez renvoyé d'une fonction, vous ne voudriez pas que str1-> pNext pointe vers quelque chose qui était sur la pile dans cette fonction.

En d'autres termes, NE PAS FAIRE:

typedef struct str_t_tag { 
    int foo; 
    int bar; 
    struct str_t_tag *pNext; 
} str_t; 

str_t *func(void) 
{ 
    str_t *pStr1 = malloc(sizeof(*pStr1)); 
    str_t str2; 
    pStr1->pNext = &str2; 

    return pStr1; /* NO!! pStr1->pNext will point to invalid memory after this */ 
} 
+0

'sizeof (* pStr1)' fonctionnerait-il si 'pStr1' n'est pas initialisé (comme c'est le cas lors du traitement de la ligne' malloc')? – Dukeling

+0

yes - sizeof est évaulé au moment de la compilation et il n'est pas nécessaire d'initialiser le contenu pour savoir quelle sera leur taille. – Vicky

0

Je ne sais pas si c'est une question spécifique à C/C++, mais je vais donner le code C/C++ comme exemple.

La seule façon que vous pouvez le déclarer: (avec des variations mineures)

typedef struct abc 
{ 
    struct abc *other; 
} abc; 

other peut pointer vers un objet sur la pile comme suit:

abc a, b; // stack objects 
b.other = &a; 

Ce n'est pas une question sur la portée , donc je passerai le commentaire sur les problèmes possibles en faisant ce qui précède.

Si, toutefois, vous souhaitez l'affecter à un objet créé dynamiquement, cet objet ne peut en aucun cas être sur la pile.

abc b; 
b.other = malloc(sizeof(abc)); // on the heap 
+0

réponse géniale et élaborée :) – stian

+1

@dexter, si cela ou toute autre réponse vous a aidé, alors s'il vous plaît upvote (en utilisant la flèche vers le haut à la gauche de la réponse) et/ou l'accepter (en utilisant la coche verte, également à la à gauche de la réponse). – Vicky

+0

@vicky, obs, désolé. – stian