2009-08-18 11 views
28

J'ai essayé de trouver ce qu'est vraiment une structure et je suis tombé sur un problème. J'ai donc 2 questions:Tableau tableau dans une affectation struct-incompatible?

1) Qu'est-ce qui est enregistré dans 'sara'? Est-ce un pointeur vers le premier élément de la structure?

2) La question la plus intéressante: Pourquoi ne compile-t-elle pas? GCC dit « test.c: 10: Erreur: types incompatibles dans l'affectation » et je ne peux pas comprendre pourquoi ...

#include <stdio.h> 

struct name { 
    char first[20]; 
    char last[20]; 
}; 

int main() { 
    struct name sara; 
    sara.first = "Sara"; 
    sara.last = "Black"; 
    printf("struct direct: %x\n",sara); 

    printf("struct deref: %x\t%s\n", *sara, *sara); 


} 

(Cette partie a été résolu par vos réponses déjà, super!) Merci de votre aide!

+0

est ici en fait une pleine dupe: http://stackoverflow.com/questions/1265117/structure-problem-in-c/ – sharptooth

+1

awww. Mais j'ai fait une recherche, vraiment: D – Patrick

Répondre

51

Cela n'a rien à voir avec struct - tableaux en C ne sont pas cessibles:

char a[20]; 
a = "foo"; // error 

vous devez utiliser strcpy:

strcpy(a, "foo"); 

ou dans votre code:

strcpy(sara.first, "Sara"); 
+4

+1 Pour 'strcpy' sur' strncpy' ... :) – GManNickG

+0

J'aurais utilisé char * first; sara.first = "Sara", puisque j'ai utilisé des tableaux de taille fixe seulement quand c'est vraiment nécessaire; Est-ce une bonne ou une mauvaise pratique (en C, pas en C++)? – gramm

+1

@gramm Si vous faites cela, vous vous engagez à gérer la mémoire dynamique, ce qui peut ne pas être nécessaire ou souhaitable. –

4

utilisez strncpy pour vous assurer que vous n'avez pas de débordement de tampon.

char name[]= "whatever_you_want"; 
strncpy(sara.first, name, sizeof(sara.first)-1); 
sara.first[sizeof(sara.first)-1] = 0; 
+1

Cela suppose que la troncation silencieuse des données n'entraîne pas l'échec de votre programme ailleurs sur la ligne. Il est généralement préférable de gérer explicitement le cas où la chaîne ne rentre pas dans le tampon, soit d'invoquer un comportement indéfini avec strcpy, soit de mettre votre programme dans un état inattendu avec strncpy. Mais je généralise - si le reste de votre programme compte pour la troncature silencieuse (par exemple, ne s'attend jamais à ce que sara.first corresponde à "whatever_you_want") alors l'état du programme n'est pas inattendu. –

+1

@onebyone ce comportement doit être documenté dans le contrat. – TimW

+0

Si cela suffit, alors pourquoi ne pas simplement documenter que la chaîne d'entrée ne doit pas être plus longue que la structure peut faire face? Le problème est de concevoir des API qui aident les clients à éviter les erreurs. OMI, ignorant silencieusement ce qui est probablement une erreur ne le fait pas. Mais comme je le dis, je généralise, et ce n'est peut-être pas une erreur. Si la fonction est appelée "StoreFirst20CharsOf", nous pouvons raisonnablement supposer que quiconque regarde le code appelant comprendra ce qu'il fait. Donc, il y a quelques utilisations pour strncpy. –

2

sara est le struct lui-même, et non pas un pointeur (à savoir la variable d'emplacement représentant sur la pile où données struct réelles sont mémorisées). Par conséquent, *sara n'a aucun sens et ne compilera pas.

+0

ah, ok ... Merci – Patrick

0

La structure Sara est un bloc de mémoire contenant les variables à l'intérieur. Il n'y a presque pas de différence entre une déclaration classique:

char first[20]; 
int age; 

et une structure:

struct Person{ 
char first[20]; 
int age; 
}; 

Dans les deux cas, vous êtes juste allouez de la mémoire pour stocker des variables, et dans les deux cas, il y aura 20 +4 octets réservés. Dans votre cas, Sara est juste un bloc de mémoire de 2x20 octets. La seule différence est qu'avec une structure, la mémoire est allouée comme un seul bloc, donc si vous prenez l'adresse de départ de Sara et sautez 20 octets, vous trouverez la "dernière" variable. Cela peut être utile parfois.

vérifiez http://publications.gbdirect.co.uk/c_book/chapter6/structures.html pour plus :).

+0

Sara est un bloc de mémoire de * au moins * 2 * 20 octets.Ce pourrait être plus, s'il y a du rembourrage. – caf

+0

Et 'offsetof (struct name, last)' n'est pas nécessairement 20, non plus (bien que ce soit certainement le cas). – caf

+0

Je ne le savais pas. Y a-t-il une possibilité de remplissage en spécifiant la taille variable? Par exemple, vitesse char non signée: 7; indicateurs de char non signés: 3; etc ... J'utilise ceci au travail et je n'ai jamais eu de problème avec le remplissage et l'alignement des données. – gramm

3

Vous pouvez également initialiser comme ceci:

struct name sara = { "Sara", "Black" }; 

Depuis (comme un cas particulier), vous êtes autorisé à tableaux de initialiser ombles de constantes de chaîne. Maintenant, en ce qui concerne ce qu'est une structure, c'est un type composé composé d'autres valeurs. Ce qui ressemble réellement à sara en mémoire est un bloc de 20 valeurs de char consécutives (auxquelles on peut se référer en utilisant sara.first, suivi de 0 ou plusieurs octets de remplissage, suivi d'un autre bloc de 20 valeurs char consécutives (auxquelles on peut se référer en utilisant sara.last) .Toutes les autres instances du type struct name sont disposées de la même manière.

Dans ce cas, il est très peu probable qu'il y ait un rembourrage, donc un struct name est juste un bloc de 40 caractères, pour lesquels vous avez un nom pour la première 20 et le dernier 20.

Vous pouvez Découvrez la taille d'un bloc de mémoire struct name en utilisant sizeof(struct name), et vous pouvez trouver où dans ce bloc de mémoire chaque membre de la structure est placé en utilisant offsetof(struct name, first) et offsetof(struct name, last).

8

Ou vous pouvez simplement utiliser l'allocation dynamique, par exemple .:

struct name { 
    char *first; 
    char *last; 
}; 

struct name sara; 
sara.first = "Sara"; 
sara.last = "Black"; 
printf("first: %s, last: %s\n", sara.first, sara.last); 
0

Vous pouvez utiliser strcpy pour le remplir. Vous pouvez également l'initialiser à partir d'une autre structure.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

struct name { 
    char first[20]; 
    char last[20]; 
}; 

int main() { 
    struct name sara; 
    struct name other; 

    strcpy(sara.first,"Sara"); 
    strcpy(sara.last, "Black"); 

    other = sara; 

    printf("struct: %s\t%s\n", sara.first, sara.last); 
    printf("other struct: %s\t%s\n", other.first, other.last); 

} 
Questions connexes