La définition d'une Structure en C avec Malloc
J'ai demandé à un question plus tôt sur la définition d'une structure à l'aide de malloc.
Ce fut la réponse m'a été donné par la majorité:
struct retValue* st = malloc(sizeof(*st));
Je montrais un ami de mon code, et nous sommes arrivés à un point d'achoppement.
Quelqu'un pourrait-il expliquer pourquoi ce code fonctionne?
De mon point de vue, *st n'a pas été définie lorsque vous malloc, alors il pourrait être n'importe quel type de déchets. Il devrait être malloc(sizeof(struct retValue))
Merci pour toute aide
Vous avez répondu à votre propre question. sizeof(struct retValue) est correct
Désolé, la question n'était pas " Est-ce correct, ou ce qui est juste?", il était " Pourquoi ce travail?'
Il pourrait aider à comprendre si vous modifiez la terminologie. Vous n'êtes pas définition une structure à l'aide de malloc, vous êtes affectation une structure à l'aide de malloc. Vous êtes à la définition de
Désolé, la question n'était pas " Est-ce correct, ou ce qui est juste?", il était " Pourquoi ce travail?'
Il pourrait aider à comprendre si vous modifiez la terminologie. Vous n'êtes pas définition une structure à l'aide de malloc, vous êtes affectation une structure à l'aide de malloc. Vous êtes à la définition de
st
, qui est un pointeur (pas une structure (struct). Le pointeur est déjà définis et disponibles pour une utilisation dans l'initialiser expression (sur le membre de droite du signe égal), il n'a pas de valeur, donc la plupart des utilisations seraient nuls. Ceci est OK, cependant, parce que sizeof n'utilise pas la valeur.
OriginalL'auteur Blackbinary | 2010-02-01
Vous devez vous connecter pour publier un commentaire.
Sizeof regarde le type de l'expression donnée, il n'a pas d'évaluer l'expression. Donc, vous avez seulement besoin de s'assurer que les variables utilisées dans l'expression sont déclarées pour que le compilateur puisse déduire de leur type.
Dans votre exemple, st est déjà déclaré comme pointeur vers une struct-retValue. Par conséquent, le compilateur est capable de déduire le type de l'expression "*st".
Bien qu'il ne regarde pas comme il est déjà déclarée dans votre code, le compilateur a déjà pris soin de tout pour vous. Toutes les déclarations dans votre code sont déplacés vers le début du bloc dans lequel elles se produisent par le compilateur. Supposons que vous écrivez
Une façon d'illustrer la connaissance qui est à la disposition du compilateur consiste à regarder l'intermédiaire de la sortie qu'il génère. Prenons cet exemple de code...
À l'aide de gcc comme un exemple et le code ci-dessus dans le main() fonction de test.c, regardons l'intermédiaire de la sortie en cours d'exécution...
Le compilateur va générer le fichier test.c.022t.cfg - Regardez et vous verrez
Note de la façon dont la déclaration a été déplacée au début du bloc et de l'argument à la fonction malloc est déjà remplacé par la valeur réelle indiquant la taille du type de l'expression évaluée. Comme l'a souligné dans les commentaires, le fait que la déclaration a été déplacé vers le haut du bloc est un détail de l'implémentation du compilateur. Cependant, le fait que le compilateur est capable de le faire et aussi d'insérer la bonne taille dans la fonction malloc de tous les spectacles que le compilateur a été en mesure de déduire les informations nécessaires à partir de l'entrée.
Personnellement, je préfère donner le véritable nom du type qu'un paramètre sizeof, mais c'est probablement une question de codage de style où je dirais que la cohérence atouts personnels de préférence.
*st
faire des "mauvaises choses".*st
est pas valide sist
ne pointent pas vers des données valides. Mais depuissizeof
ne pas évaluer son argument, il est acceptable d'utiliser*st
comme un opérande desizeof
, même sist
estNULL
par exemple.En fait, la question était "comment/pourquoi est-ce le travail, malgré le fait que saint ne peut pas être déréférencés au moment malloc besoin de savoir combien d'espace à allouer à"...
Mettre une déclaration au début du bloc dans l'analyse de la version du code est un détail d'implémentation. Le compilateur n'est pas nécessaire de le faire, même si la vôtre arrive, et l'interlocuteur du code fonctionne si le compilateur ne ou pas. Le code suivant ne compile pas, montrant que la déclaration n'est pas "vraiment" déplacé:
sizeof(*st); char *st = 0;
.En plus de ce que Steve Jessop a dit, permettez-moi d'ajouter que ce n'est pas le code de réarrangement qui détermine si le
sizeof
œuvres, mais plutôt une déclaration/définition de portée. Votre réponse attribue un comportement standard de manière incorrecte sur un détail d'implémentation.J'ai reformulé la réponse de sorte qu'il n'est plus met l'accent sur la réorganisation de la raison, mais seulement comme un exemple de ce que le compilateur est capable de déduire à partir de l'entrée. Merci pour vos commentaires les gars.
OriginalL'auteur VoidPointer
La
sizeof
opérateur n'a pas fait évaluer son opérande - il semble juste à son type. Ceci est fait au moment de la compilation plutôt que de l'exécution. Donc, il peut en toute sécurité être effectuée avant que la variable a été attribué.sizeof
regarde *saint et dit: "Oh c'est un pointeur!" et puis alloue suffisamment de mémoire pour un pointeur. Il ne se soucie pas de ce qu' *st est en fait la tenue. Droit?Non, c'est l'inverse.
*st
signifie "la chose que saint points de de", de sorte que le compilateur renvoie la taille de la structure, pas de la taille du pointeur.À proximité:
st
est un pointeur, mais*st
est une struct. De sorte qu'il ressemble à*st
et dit: "Oh, c'est unstruct retValue
!" et puis alloue suffisamment de mémoire pour un retValue structure. Le contenu réel de*st
n'a pas d'importance.Ah, si proche. merci. Doit avez juste confus comme je l'ai tapé parce que je pensais struct dans ma tête!
L'Argument de l'évaluation n'a rien à voir avec cela.
OriginalL'auteur interjay
Ce qui compte c'est la déclaration/définition de la structure type et non pas la définition d'un objet d'une telle classe. Au moment où vous atteignez la
malloc
, une déclaration/définition ont été rencontrées par le compilateur, vous auriez touché à une erreur du compilateur autrement.Le fait que
sizeof
n'évalue pas ses opérandes est un problème.Un mineur nit: n'oubliez pas que nous besoin des parenthèses lorsque nous fournissons des noms de type de
sizeof
comme dans:et pas dans le cas des objets, nous n'avons tout simplement:
Voir la norme:
OriginalL'auteur dirkgently
En C,
sizeof
est un opérateur, et n'a pas d'évaluer son argument. Qui peut conduire à "intéressant" des effets, que quelqu'un de nouveau à C n'est pas nécessairement anticiper. J'ai mentionné plus en détail dans ma réponse à la "les plus Étranges de la langue de la fonction" question.OriginalL'auteur Alok Singhal