objective-C, C'est du C?

2»

Réponses

  • schlumschlum Membre
    novembre 2007 modifié #32
    dans 1195902061:

    De plus, rien ne t'empêches de définir ton compteur entre les directives @interface et @end de ta classe (après les accolades, puisque tu peux pas définir de variable d'instance statiques), il t'avertira que ta variable compteur n'est pas utilisée mais en fait elle le sera. Voire tu peux même les définir entre les directives @implementation et @end et en plus tu auras un warning de moins.


    Effectivement, après les accolades ça fonctionne ; ça revient au même que de la mettre en dehors des dites directives... Mais du coup (en mettant de côté le fait que c'est assez laid de la définir à  cet endroit), ça fournit une variable statique à  tous les fichiers de sources qui incluent ce header !

    Par contre, en faisant des tests, je suis tombé sur un truc pas banal... Apparemment on peut définir des variables "static" locales qui n'interfèrent pas avec les globales du même nom et avec même un type différent...

    static int test = 0;<br /><br />int main(int argc,char *argv&#91;])<br />{<br />  static float test = 1.;<br />  return 0;<br />}
    


    Ca ne me paraà®t pas très logique tout ça...  ???

    PS : les avertissements "defined but not used" que l'on a lorsqu'on la déclare dans le .h au lieu de la déclarer dans le .m, c'est justement ceux qui proviennent des autres fichiers incluant le .h et qui n'utilisent pas la variable statique !
  • psychoh13psychoh13 Mothership Developer Membre
    novembre 2007 modifié #33
    Bah si c'est tout à  fait logique au contraire, c'est simplement une définition d'une nouvelle variable dans un sous-bloc :

    int i = 0;<br />void fonction(void)<br />{<br />&nbsp; &nbsp; int i = 1;<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; int i = 2;<br />&nbsp; &nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = 3;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;i = %d&#092;n&quot;, i);<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;i = %d&#092;n&quot;, i);<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; printf(&quot;i = %d&#092;n&quot;, i);<br />}
    


    ça t'affichera 3, 2, 1...
    Donc tes variables statiques seront strictement restreintes aux blocs dans lesquels elles sont définies.
  • Philippe49Philippe49 Membre
    21:59 modifié #34
    dans 1196063710:

    Donc tes variables statiques seront strictement restreintes aux blocs dans lesquels elles sont définies.


    C'est ce que je vous disais dans mon dernier post.
    En C, la notion de statique est définie par la visibilité (locale) et la durée de vie (globale)
  • tabliertablier Membre
    21:59 modifié #35
    De retour de weekend, j'ai lu les différents posts ci-dessus.
    Les variables de classe existent en C++ mais pas en Objective-C, C'est écrit dans tout les bouquins sur Obj-C.
    Mon problème initial est un problème de fainéantise! Le voulais écrire en un coup une structure et son initialisation sans passer par des tas d'affectations de valeurs.
    Comme l'initialisation ne marche pas entre le {} de @interface je l'ai mis en dehors. Mais comme je souhaite travailler avec des NSSTring j'ai modifier la structure et j'ai écris:
    #import &lt;Cocoa/Cocoa.h&gt;<br /><br />static struct le_champ {<br />&nbsp;  NSSTring	*lenom ;<br />&nbsp;  int		&nbsp; &nbsp; letype ;<br />} DVDchamps[4] = { {@&quot;zero&quot;, 0}, {@&quot;un&quot;, 1}, {@&quot;deux&quot;, 2}, {@&quot;trois&quot;, 3} } ;<br /><br />@interface leControl : NSObject<br />{<br />&nbsp; IBOutlet NSWindow *o_fenetre ;<br />&nbsp; IBOutlet NSMatrix *o_radio ;<br />&nbsp; IBOutlet NSButton *o_swich1 ;<br />&nbsp; IBOutlet NSButton *o_switch2 ;<br />&nbsp; IBOutlet NSTextField *o_texte ;<br />}<br />- (IBAction)a_annule:(id)sender ;<br />- (IBAction)a_ok:(id)sender ;<br />@end<br />
    


    Je n'ai pas d'erreur à  la compilation. Mais si j'essaie de récupérer un nom:
    NSString *truc = [NSString stringWithString:DVDchamps[1].lenom] ;
    

    ça ne marche pas !
    Bien sur je vais faire autrement, mais j'aimerais bien savoir pourquoi ça ne marche pas. J'obtiens comme valeur: "invalide".
  • psychoh13psychoh13 Mothership Developer Membre
    21:59 modifié #36
    Peut-être parce que tu as mis une majuscule en trop...
    NSSTring au lieu de NSString...
  • schlumschlum Membre
    novembre 2007 modifié #37
    dans 1196063710:

    Bah si c'est tout à  fait logique au contraire, c'est simplement une définition d'une nouvelle variable dans un sous-bloc :

    int i = 0;<br />void fonction(void)<br />{<br />    int i = 1;<br />    {<br />        int i = 2;<br />        {<br />            int i = 3;<br />            printf(&quot;i = %d&#092;n&quot;, i);<br />        }<br />        printf(&quot;i = %d&#092;n&quot;, i);<br />    }<br />    printf(&quot;i = %d&#092;n&quot;, i);<br />}
    


    ça t'affichera 3, 2, 1...
    Donc tes variables statiques seront strictement restreintes aux blocs dans lesquels elles sont définies.


    Oui, bien sûr, pour des variables automatiques ça me paraà®t tout à  fait logique !
    C'est dans le cadre de la définition de "static" que ça me paraà®t illogique...

    Si une variable "static" est valable dans toute l'unité de compilation, comment se fait-il que l'on puisse dans la même unité de compilation en définir deux de même nom et de type différent, et qui ont des valeurs indépendantes ?
    C'est ça qui me choque...  ;)


    PS : en pratique, je n'ai jamais utilisé le mot-clé "static" ailleurs que dans le cadre de fonctions virtuelles pures en C++ ; comme j'ai pas revu la théorie C depuis un bail, ça m'échappe un peu... Il faudrait que je replonge le nez un peu dans Kernighan et Ritchie :P
  • psychoh13psychoh13 Mothership Developer Membre
    21:59 modifié #38
    Les blocs {} sont une unité de compilation. (c'est pas le nom exact mais bon pas grave) Comme le dit Philippe :

    dans 1196064037:
    En C, la notion de statique est définie par la visibilité (locale) et la durée de vie (globale)
  • schlumschlum Membre
    novembre 2007 modifié #39
    Bon, ça fait un bail que j'ai quitté l'école et la théorie, et je me sens un peu largué sur les définitions et les utilités de ces différentes classes de variables  :crackboom:- ;D (que je n'utilise jamais en fait... ???)

    En tout cas, apparemment la visibilité des variables "static" est plus limitée que celle des variables "auto", puisque si on utilise des variables "auto" de même nom dans 2 fichiers en dehors des blocs {}, ça pose problème au lien. Pourtant, les "auto" ont aussi une visibilité "locale", mais elle dépasse sans doute les frontières des fichiers.  :)


    [Edit] Ah, je crois me souvenir qu'il faut utiliser "extern" pour voir la variable "auto" d'un autre fichier...
  • schlumschlum Membre
    novembre 2007 modifié #40
    Ah, je crois que je saisis mieux le "static" avec ce test... Ca commence à  me revenir...

    - (id) init {<br />	static int cpt;<br />	self = [super init];<br />	if (self != nil) {<br />		++cpt;<br />		NSLog(@&quot;cpt = %d&quot;,cpt);<br />	}<br />	return self;<br />}
    


    Effectivement, visibilité "locale", on ne la voit pas ailleurs ; durée de vie globale, à  chaque nouvelle instance, elle s'incrémente.

    Bon, c'est bien beau tout ça, mais au final... ça sert dans quelles situations ? :P
  • psychoh13psychoh13 Mothership Developer Membre
    21:59 modifié #41
    Bah par exemple tu peux empêcher qu'une méthode s'exécute plusieurs fois :

    + (void)initialize<br />{<br />&nbsp; &nbsp; static BOOL beenThere = NO;<br />&nbsp; &nbsp; if(!beenThere)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; // du code à  n&#39;exécuter qu&#39;une seule fois<br />&nbsp; &nbsp; &nbsp; &nbsp; beenThere = YES;<br />&nbsp; &nbsp; }<br />}
    


    Bon c'est pas un bon exemple cette méthode, parce qu'il est plus propre d'utiliser : +class :

    + (void)initialize<br />{<br />&nbsp; &nbsp; if(self == [MaClass class])<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; // du code à  exécuter que pour MaClasse<br />&nbsp; &nbsp; }<br />}
    


    C'est aussi utiliser pour déclarer des structures qu'on va transmettre à  une fonction, comme dans le cas des dégradés.
  • schlumschlum Membre
    21:59 modifié #42
    dans 1196072013:

    C'est aussi utilisé pour déclarer des structures qu'on va transmettre à  une fonction, comme dans le cas des dégradés.


    Des "dégradés" ? Là  je veux bien un exemple 
  • psychoh13psychoh13 Mothership Developer Membre
    novembre 2007 modifié #43
    Des dégradés de couleurs quand tu dessines sur une vue :

    // Fonction pour calculer le dégrader :<br />static void myCalculateShadingValues (void *info,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const float *in,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; float *out)<br />{<br />&nbsp; &nbsp; float v;<br />&nbsp; &nbsp; size_t k, components;<br />&nbsp; &nbsp; static const float c&#91;] = {1, 0, .5, 0 };<br /> <br />&nbsp; &nbsp; components = (size_t)info;<br /> <br />&nbsp; &nbsp; v = *in;<br />&nbsp; &nbsp; for (k = 0; k &lt; components -1; k++)<br />&nbsp; &nbsp; &nbsp; &nbsp; *out++ = c[k] * v;<br />&nbsp; &nbsp; &nbsp;*out++ = 1;<br />}
    


    Et voici la fonction pour créer la fonction qui va dessiner le dégradé :

    static CGFunctionRef myGetFunction (CGColorSpaceRef colorspace)<br />{<br />&nbsp; &nbsp; size_t components;<br />&nbsp; &nbsp; static const float input_value_range [2] = { 0, 1 };<br />&nbsp; &nbsp; static const float output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };<br />&nbsp; &nbsp; static const CGFunctionCallbacks callbacks = { 0,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;myCalculateShadingValues,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL };<br /> <br />&nbsp; &nbsp; components = 1 + CGColorSpaceGetNumberOfComponents (colorspace);<br />&nbsp; &nbsp; return CGFunctionCreate ((void *) components,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; input_value_range,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; components,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output_value_ranges,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;callbacks);<br />}
    


    Tu vois que tu crées des constantes statiques pour qu'elles vivent encore après la fin de la fonction et tu en transmets l'adresse à  une autre fonction pour pouvoir l'utiliser dans ton dégradé.
    C'est comme ça qu'on faisait les dégradés avant Leopard. :D

    PS : c'est extrait de la documentation d'Apple sous Tiger (Painting an Axial Shading), ça te crée un dégradé allant du noir vert le magenta.
  • Philippe49Philippe49 Membre
    21:59 modifié #44
    dans 1196069194:


    Bon, c'est bien beau tout ça, mais au final... ça sert dans quelles situations ? :P



    En cours, je vends cette notion avec le calcul paresseux :
    La suite de Fibonacci u(n+2)=u(n+1)+u(n) est une cata si on la programme récursivement (en 2^n).
    Par contre, si on stocke à  chaque récursion les nouvelles valeurs calculées à  l'aide d'un tableau défini statiquement, ainsi que le rang n de la dernière valeur connue, on trouve au prix d'un encombrement mémoire, un algorithme linéaire.


  • schlumschlum Membre
    novembre 2007 modifié #45
    Ah ouais... Effectivement, l'exemple des dégradés me dit quelque-chose ; j'en avais bouffé avec DxO Optics Pro pour faire des dégradés dans des bezierPath... Faudrait que je regarde si on avait utilisé des "static"  o:)

    Quant à  calculer récursivement le n-ième terme de la suite de Fibonacci, effectivement c'est une drôle d'idée  ;D
    J'imagine que ça se présente de cette manière :

    #include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br /><br />unsigned long long fibo(unsigned long i);<br /><br />int main(int argc,char *argv&#91;])<br />{<br />  printf(&quot;%llu&#092;n&quot;,fibo(40));<br />  return 0;<br />}<br /><br />unsigned long long fibo(unsigned long i)<br />{<br />  static unsigned long long fib[101] = {0};<br />  if(i&gt;100) {<br />    printf(&quot;Erreur !&#092;n&quot;);<br />    exit(1);<br />  }<br />  if(i==0)<br />    return 0;<br />  else if(i==1)<br />    return 1;<br />  else {<br />    if(fib[i]==0)<br />      fib[i] = fibo(i-1)+fibo(i-2);<br />    return fib[i];<br />  }<br />}
    


    Ceci-dit, on peut le faire aussi avec une variable "auto" en dehors du scope des fonctions... Peut-être moins propre et moins rapide, vu que les "static" ne sont pas sur la pile.
Connectez-vous ou Inscrivez-vous pour répondre.