2010-01-02 5 views
2

je viens d'un fond de php et je suis en train d'étudier cette page http://cocoadevcentral.com/articles/000081.php avant de mettre les pieds dans certaines des choses plus difficiles en ce qui concerne Objective-Caide compréhension typedef struct

si je tape quelque chose comme ça

typedef struct { 
int lengthInSeconds; 
int yearRecorded; 
} Song; 

et lors de la définition d'une fonction ou d'une variable de type Song, qu'est-ce que cela signifie? Je comprends qu'en définissant une fonction comme un int ou peut-être un flottant, la sortie serait liée à son ensemble de types. mais quand je fais quelque chose comme ça

Song myvariable; 
or 
Song myfunction(int params) { } 

what type is Song setting? 

grâce

Répondre

1

Voici un article de wikipedia sur les struct de C.

http://en.wikipedia.org/wiki/Struct_%28C_programming_language%29

+0

J'ai lu l'article sur wikipedia. mais ne comprends pas son but, serait-il semblable à l'écriture de classes en php? – SarmenHB

+0

Structs sont semblables à des cours dans leur groupe jusqu'à plusieurs autres variables (dans ce cas, deux ints) dans un paquet autonome des données (voir d'autres réponses par NSResponder et lpthnc). Les idéologies d'une structure C et d'une classe PHP sont plutôt différentes. –

2

En supposant que Objective C est très proche de C, vous faites ceci:

Song myvariable; // creates the truct in memory 
myvariable.lengthInSeconds = 10; 
myvariable.yearRecorded = 2010; 

Je ne peux pas dire ce que la fonction ne parce que vous ne l'avez pas donné son impl.

Voici comment résoudre la fonction de faire quelque chose « utile »:

Song myfunction(int params) { 
    Song ret; 
    ret.lengthInseconds = params * 69; 
    ret.yearRecorded = 3*5*7*9*11; 
    return ret; 
} 

(Jut pour illustrer que la fonction peut faire tout ce que ...

2

Dans le premier cas:

Song myvariable; 

vous déclarez mavariable être une instance de la struct vous avez déclaré dans votre typedef.

Dans le second cas:

Song myfunction(int params) { } 

Vous déclarez une fonction qui prend un entier, et retourne un morceau. Comme il n'y a pas de code dans les accolades, vous ne retournez rien et le compilateur signale une erreur dans votre code.

+0

Je voudrais simplement ajouter que le premier moyen de « assez d'espace mémoire de réserve pour maintenir une structure de chanson de type et appellent mavariable » tandis que le second est: « Je promets que cette fonction retourne une structure de type Song ». –

15

Je pense que cela vous aiderait le plus à savoir ce qui se passe dans la tête du compilateur. En utilisant votre exemple:

typedef struct { 
int lengthInSeconds; 
int yearRecorded; 
} Song; 

Il y a en fait deux choses qui se passent ici. La première est que vous définissez un anonyme struct:

struct { 
int lengthInSeconds; 
int yearRecorded; 
} 

Ce anonyme struct peut être utilisé partout un type (par exemple int ou const char*) pourrait être utilisé. L'exemple suivant est en fait valable, bien que personne ne devrait jamais écrire du code comme ceci parce qu'il est un cauchemar d'entretien:

struct { 
int lengthInSeconds; 
int yearRecorded; 
}* GetSongInfo(const char* songName); 

Ceci déclare une fonction qui obtient les informations d'une chanson avec un nom donné (noms en supposant sont uniques, une hypothèse invalide dans la vie réelle) et renvoie un pointeur vers un struct avec ses métadonnées.

Je en ai parlé comme un « anonyme struct » parce que la forme struct nommée ressemble à ceci:

struct Song { 
int lengthInSeconds; 
int yearRecorded; 
} 

Maintenant, vous pouvez vous référer à cette struct par nom, mais pas de la façon que vous pensez venir à partir de langues autres que C! Plus précisément, la fonction ci-dessus serait maintenant déclarée:

struct Song* GetSongInfo(const char* songName); 

Notez que le nom du type est struct Song et pas seulement Song! En fait, struct s ont un espace de noms distinct de leur propre ... donc il n'y a rien dans la langue pour garantir que struct Song et Song sont la même chose! Je ne sais pas si l'objectif C maintient cette folie, mais je parie que c'est sûr.

La deuxième chose est que vous alimentez cette structure anonyme à typedef. typedef prend simplement un type et définit un nom pour celui-ci que vous pouvez utiliser plus tard. Donc, vous dites vraiment "un Song est un alias pour que struct {...} je viens de déclarer."

En typedef ing Song place, vous pouvez écrire:

Song* GetSongInfo(const char* songName); 

(Oui, je sais qu'il serait préférable de revenir const Song*, mais c'est à côté du point.)

Il peut vous intéresser à notez que C a beaucoup typedefs dans ses bibliothèques standard, destinées à séparer les particularités d'une plate-forme à partir des particularités de la norme C. Par exemple, <unistd.h> définit size_t, le type entier qui représente une taille (et est le type de retour de la fonction sizeof() intégrée), et par extension, le type que vous devez passer à des fonctions telles que malloc(). Il y a aussi l'en-tête <stdint.h> récent qui définit les types entiers par leur taille en bits, par ex. pour un entier non signé de 8 bits. La ligne <stdint.h> ressemble probablement quelque chose comme:

typedef unsigned char uint8_t; 

Comme la plupart des plates-formes ont des caractères 8 bits. (J'ai programmé pour certaines plates-formes comme TI DSP où un char n'était pas 8 bits, en général il était 16, car le processeur ne pouvait pas accéder à des parties de mots.) Ignorons les plates-formes dégénérées pour le moment.)

Enfin, pour expliquer vos exemples:

Song myvariable; 

Ce stockage pour une déclare la structure Song. S'il se trouve dans une définition de fonction, ce stockage sera alloué sur la pile et relâché lorsque la fonction se terminera. Si elle est en dehors d'une définition de fonction, elle sera allouée comme globale. Dans les deux cas, il sera non initialisé, ce qui en C signifie qu'il peut contenir des valeurs aléatoires. C ne garde pas trace des variables non initialisées ou les définit comme "non initialisées" ou comme PHP et Python. C ne jette pas d'exceptions non plus.

Song myfunction(int params) { } 

Ceci définit une fonction qui prend un nombre entier et renvoie une structure Song.L'instruction return de la fonction doit recevoir un Song. Par exemple:

Song myfunction(int params) 
{ 
    Song result; 
    result.lengthInSeconds = GetSongLength(params); 
    result.yearRecorded = GetSongYear(params); 
    return result; 
} 

Cette fonction alloue de l'espace sur la pile pour une Song, remplit ses champs en appelant des fonctions qui renvoient int s, puis return copie la structure de result dans l'espace réservé à la valeur de retour, et enfin le stockage pour result est libéré lorsque la fonction se termine. Habituellement, le compilateur peut optimiser la copie implicite dans l'instruction return. En outre, il peut y avoir une autre (éventuellement optimisé) copie à partir du stockage de valeur de retour vers une destination finale, par exemple quand vous dites:

Song foundSongInfo = myfunction(params); 

Par ailleurs, le retour struct s sur la pile est désapprouvée, car les compilateurs peut généralement optimiser mieux si la valeur de retour s'inscrit dans un registre (c.-à-d. est un type simple). (Il existe des exceptions en C++ avec la surcharge des opérateurs, mais c'est hors-sujet.) Une meilleure définition serait:

void myfunction(int params, Song* found) 
{ 
    found->lengthInSeconds = GetSongLength(params); 
    found->yearRecorded = GetSongYear(params); 
} 

Cela évite toutes les copies supplémentaires. Vous l'appelez comme ceci:

Song foundSongInfo; 
myfunction(params, &foundSongInfo); 

Ceci est un cas où deux lignes peuvent être plus rapides que l'un.

J'ai peut-être manqué des choses, faites-moi savoir si cela a du sens ...

+0

L'une des meilleures réponses que j'ai jamais vues sur StackOverflow. Merci! –