[Powered by Google Translate] Parlons un peu de structures. Structures nous fournir un moyen de regrouper un ensemble de variables entre elles dans un joli paquet. Il est probablement plus facile de voir un exemple tout de suite, alors nous disons struct, puis en ouvrant accolade, et dans cette structure, nous aurons un âge int, un char * nom, et c'est tout. Il peut sembler bizarre avec un point-virgule après une accolade, mais il est en fait nécessaire avec structs. Tout type valide peut aller dans la définition de la structure. Ici, nous avons utilisé un int et un char *, mais vous pouvez aussi utiliser un tableau, de dire, de 100 éléments ou même une autre structure. Lorsque vous utilisez structs en C, vous créez de nouveaux types sur un ensemble de types autres. Ici, nous faisons un nouveau type sur un nombre entier et un char *. Comme nous le verrons plus tard, un type struct est dans beaucoup de manières équivalentes à tout autre type que vous êtes habitué. Habituellement, je vais comparer la façon dont un type struct est similaire à un type entier. Bien que le code que nous avons écrit est valide C, ce n'est pas très utile, et clang nous donnera un avertissement. Rappelez-vous comment structs et ses semblables sont? Eh bien, nous venons de dire essentiellement int, ce qui n'est pas une ligne très utile. Donc, nous allons effectivement déclarer une variable de ce type en lui donnant un nom avant le point-virgule. Nous allons appeler l'étudiant variable. Maintenant, nous avons déclaré un étudiant variable appelée avec le type proposée par le struct. Comment arrivons-nous à les variables à l'intérieur de la structure? Techniquement, les noms de ces variables sont membres. Pour accéder à un membre en particulier dans une structure étudiant, vous ajoutez un point à un nom de variable, suivi du nom du membre que vous voulez. Donc, ici, les 2 seules possibilités valables sont student.age et student.name. Et nous pouvons faire quelque chose comme student.age = 12 et student.name = étudiant. Maintenant, si nous voulions faire un étudiant de deuxième? Vous pourriez penser à copier et coller ces lignes et changer un élève à 2 ou quelque chose, et cela fonctionnera, mais techniquement, étudiant et étudiant 2 n'ont pas le même type. Voir, vous ne serez pas en mesure de les affecter à un autre. C'est parce que, jusqu'à présent, votre structure a été anonyme. Nous devons lui donner un nom. Pour ce faire, nous insérons le nom de la structure après le mot struct. étudiant, suivie par la définition. Nous pouvons toujours immédiatement déclarer une variable de type struct étudiant, comme nous le faisions auparavant. Nous l'appellerons S1 En donnant à la structure d'un nom, nous pouvons maintenant utiliser étudiant struct dans presque exactement la même manière que nous utiliserions int. Ainsi, nous pouvons déclarer une variable de type struct étudiant, comme struct étudiant S2. Comme les tableaux, les structures fournissent une syntaxe d'initialisation de raccourci, de sorte que nous pouvons dire, struct étudiant S2 est égal à accolade gauche 3, S2. Ici, S2.age sera de 3, et S2.name pointera vers S2. Pensez à toutes les choses que vous pouvez faire avec un type int et la plupart d'entre eux que vous pouvez faire avec un type struct étudiant. Nous pouvons utiliser un étudiant struct comme type de paramètre d'une fonction. Nous pouvons utiliser étudiant struct l'intérieur d'une structure nouvelle. Nous pouvons avoir un pointeur à un étudiant struct. Nous pouvons faire la taille de l'étudiant struct. Étudiant struct est un type comme int est un type. Nous pouvons également attribuer S1 à S2 puisque les deux sont du même type, de sorte que nous pouvons faire S1 = S2. Qu'est-ce qui se passe si nous faisons S1.age = 10? Est-ce que le changement S2 du tout? Encore une fois, pensez aux structs juste que les entiers réguliers. Si nous attribuons une certaine X int dans une certaine int Y, comme X = Y puis modifiez X, comme dans X + +, Y ne change pas du tout? Y ne change pas ici, et donc ni ne S2 ci-dessus. S2.age reste 3. Mais il faut noter que lorsque l'affectation d'un struct à l'autre, tous les pointeurs indiquent toujours la même chose, car ils viennent d'être copiés. Si vous ne voulez pas les pointeurs doivent être partagées, vous devrez gérer manuellement que, peut-être par une malicking bloc de mémoire pour l'un des pointeurs pour pointer vers et la copie des données sur. Il pourrait être gênant d'avoir à écrire des élèves struct partout. L'utilisation d'un type de def, nous pouvons faire Type de def struct et nous allons l'appeler étudiant. Maintenant, nous pouvons utiliser des étudiants partout que nous utilisions des étudiants struct. Ce type de définition est une struct anonyme et il appelle cela des élèves. Mais si nous gardons aussi l'identificateur de l'étudiant à côté de la struct mot, comme dans typedef struct étudiant, nous pourrions utiliser à la fois des élèves et des étudiants struct interchangeable maintenant. Ils n'ont même pas d'avoir le même nom. Nous pourrions taper étudiant struct def à Bob puis struct étudiant et Bob serait types interchangeables. Quel que soit le type de def, nous avons besoin de l'identifiant à côté de struct si la définition de la structure est récursive. Par exemple, Type struct def noeud et il sera défini comme un int val et il aura un pointeur qui pointe vers un autre nœud struct., comme dans noeud struct * à côté. Et puis, nous l'appellerons nœud. Cette structure est récursive, puisque la définition de struct noeud contient en son sein un pointeur vers un noeud de structure. Notez que nous avons à dire struct noeud * suivant à l'intérieur de la définition de la structure du noeud, depuis la définition de type n'a pas encore fini de nous permettre de simplifier cette juste noeud * suivant. Vous en apprendrez plus sur structs similaires à ce lorsqu'ils traitent avec les listes chaînées et les arbres. Qu'en est-il structs dans une fonction? C'est aussi tout à fait valable. Nous pourrions avoir annuler fonctions qui prend comme argument, étudiant s et fait quelque chose avec cet élève. Et puis on peut passer comme struct étudiant comme ceci. Fonction de S1 d'avant. La structure se comporte exactement comme un entier serait lorsqu'il est passé à une fonction. Func reçoit une copie de S1 et ne peut donc pas modifier S1; plutôt que la copie de celui-ci qui est stocké dans S. Si vous voulez utiliser cette fonction pour être en mesure de modifier S1, fonctions aurez besoin de prendre un étudiant * S, et vous aurez à passer S1 par adresse, comme ceci. Étudiant * S, fonctions et S1. Il ya une autre raison de passer par l'adresse ici. Que faire si notre structure contient 100 champs? Chaque fois que nous passons à un élève de fonction, notre programme a besoin de copier l'ensemble de ces 100 champs en fonction de l'argument de S, même si elle n'utilise jamais la grande majorité d'entre eux. Donc, même si fonction n'a pas l'intention de modifier l'étudiant, si peut toujours être utile de passer par adresse. Ok, si nous voulons créer un pointeur vers une struct? Nous pourrions faire quelque chose comme étudiant * S est égal à malloc taille de l'élève. Notez que la taille du marche toujours ici. Alors, comment pouvons-nous maintenant accéder au membre âge du bloc que les points de S? Vous pourriez d'abord penser à faire * S.age = 4, mais ce ne sera pas tout à fait fonctionné. Depuis cela va vraiment être interprété comme S.age * entre parenthèses = 4, qui ne seront même pas compiler, puisque S n'est pas une structure ou plutôt un pointeur vers une struct, et si le point ne fonctionne pas ici. Nous pourrions faire (* S). Âge = 4 mais les parenthèses sont parfois ennuyeux et confus. Heureusement, nous avons un opérateur flèche spéciale qui ressemble à S-> age = 4. Ces 2 façons de référencer l'âge sont équivalentes et nous n'avons pas vraiment besoin de plus l'opérateur flèche, mais cela rend les choses plus joli. Comme S est un pointeur vers un bloc de mémoire qui contient la structure, vous pouvez penser à S> âge comme suit la flèche du pointeur et de saisir le membre âge. Alors pourquoi devrions-nous toujours utiliser des structs? Il est certainement possible de s'en tirer avec seulement des nombres entiers primitifs, caractères, des pointeurs et autres que nous sommes habitués à; au lieu de S1 et S2 avant, nous aurions pu avoir âge1, age2, nom1, nom2 et tout à variables séparées. C'est très bien avec seulement 2 étudiants, mais que faire si nous avons eu 10 d'entre eux? Et si, au lieu de seulement 2 champs, la structure étudiant avait 100 champs? AMP, les cours, la couleur des cheveux, le sexe, et ainsi de suite. Au lieu de seulement 10 structures, nous avons besoin de 1000 variables séparées. Aussi, considérons une fonction qui prend cette structure avec 100 champs avec son seul argument et affiche tous les champs. Si nous n'avons pas utilisé une structure, chaque fois que nous appelons cette fonction, nous avons besoin de passer à tous les 100 variables, et si nous avons 100 variables pour étudiant 1, et 100 variables pour les étudiants 2, nous devons être sûrs de ne pas accidentellement transmettre certaines variables de l'étudiant 1 et certaines variables de l'élève 2. Il est impossible de faire cette erreur avec une struct, puisque tous les 100 variables sont contenues dans un seul paquet. Juste quelques notes finales: Si vous avez tout compris jusqu'à ce point, tant mieux. Le reste de la vidéo est juste pour être complet. Parce que structs peut contenir n'importe quel type de pointeur, ils peuvent aussi contenir des pointeurs de fonction. Si vous êtes familier avec la programmation orientée objet, cela fournit un moyen d'utiliser des structs à programmer dans un style orienté objet. En savoir plus sur les pointeurs de fonction à un autre moment. En outre, vous pouvez parfois avoir 2 structs dont les définitions dépendent les uns des autres. Par exemple, nous pourrions avoir struct A, qui est définie comme un pointeur vers une struct B, struct B * X, et maintenant nous pouvons avoir une struct B qui est défini comme un pointeur une structure de A, struct A * Y. Mais ce ne sera pas compilé, puisque B struct n'existe pas à l'époque que struct A est en cours d'élaboration. Et si nous échangeons struct A et B struct, alors que nous venions de se retrouver avec le même problème; cette fois, avec struct A existant pas. Pour résoudre ce problème, nous pouvons écrire struct B; avant la définition de struct A. C'est ce qu'on appelle une déclaration anticipée. Cela permet juste savoir au compilateur que struct B est un type valide qui sera entièrement défini plus tard ou ailleurs. Mon nom est Rob Bowden, et c'est CS50. [CS50.TV]