2013-05-14 4 views
2

J'apprenais C et j'ai rencontré un problème avec les structures.Tableau des pointeurs struct - overrides struct

Supposons que je la struct suivante:

typedef struct { 
    int x; 
} Structure; 

int main (void) { 
    Structure *structs[2]; 
    for(int i = 0; i < 2; i++) { 
    Structure s = {i}; 
    structs[i] = &s; 
    } 
    for(int i = 0; i < 2; i++) { 
    printf("%d\n", structs[i]->x); 
    } 

    return 1; 
} 

La sortie est:

1 
1 

Je ne comprends pas pourquoi la nouvelle structure est overring l'ancien.

Ce pourrait être un problème stupide. Mais je ne comprends pas.

Merci!

Résolu:

typedef struct { 
    int x; 
} Structure; 

int main (void) { 
    Structure *structs[2]; 
    for(int i = 0; i < 2; i++) { 
    Structure *s = (Structure *)malloc(sizeof(Structure)); 
    s->x = i; 
    structs[i] = s; 
    } 
    for(int i = 0; i < 2; i++) { 
    printf("%d\n", structs[i]->x); 
    free(structs[i]); 
    } 

    return 1; 
} 

Répondre

4

L'objet s ne vit pas au-delà de la portée de la première boucle for. Le stockage de son adresse est inutile, et le déréférencement est comportement indéfini.

+0

Merci! Je l'ai! J'ai changé mon code pour utiliser le tas comme stockage. – user2221323

3

Le code a un comportement indéfini. Vous détenez la référence d'une variable automatique locale.

for(int i = 0; i < 2; i++) { 
    Structure s = {i}; 
    structs[i] = &s; 

} // life time of s ends here 

Tous les paris sont désactivés car le code a UB. Donc, peu importe le résultat obtenu.

+0

Ce n'est pas que la variable est locale - si elle était statique, aucun UB ne serait ici. La terminologie correcte (complète) est la variable "locale automatique" *. –

+0

@ H2CO3: En fait, c'est * "objet avec bloc de portée et durée de stockage automatique" *. Je ne crois pas que la norme utilise le terme «local» pour cela - ou «variable» d'ailleurs. –

+0

@KeithThompson A droite, plutôt "bloc de portée" - mais je n'ai pas laissé entendre "variable" faisait partie de la terminologie soit (c'est pourquoi il est hors les guillemets et les italiques). –

1

La zone Structs s = {i}; a uniquement une portée dans la boucle for où vous l'avez déclarée. Une fois que vous avez quitté cette boucle, elle n'existe plus, même si vous avez toujours un pointeur. Tout est comportement indéfini après cela.