Recherche…


Portée du bloc

Un identificateur a une portée de bloc si sa déclaration correspondante apparaît dans un bloc (la déclaration de paramètre dans la définition de fonction s'applique). La portée se termine à la fin du bloc correspondant.

Aucune autre entité avec le même identifiant ne peut avoir la même portée, mais les étendues peuvent se chevaucher. En cas de chevauchement des étendues, la seule visible est celle déclarée dans la portée la plus profonde.

#include <stdio.h>

void test(int bar)                   // bar has scope test function block
{
    int foo = 5;                     // foo has scope test function block
    {
        int bar = 10;                // bar has scope inner block, this overlaps with previous test:bar declaration, and it hides test:bar
        printf("%d %d\n", foo, bar); // 5 10
    }                                // end of scope for inner bar
    printf("%d %d\n", foo, bar);     // 5 5, here bar is test:bar
}                                    // end of scope for test:foo and test:bar

int main(void)
{
    int foo = 3;         // foo has scope main function block

    printf("%d\n", foo); // 3
    test(5);
    printf("%d\n", foo); // 3
    return 0;
}                        // end of scope for main:foo

Fonction Prototype Scope

#include <stdio.h>

/* The parameter name, apple, has function prototype scope.  These names
   are not significant outside the prototype itself.  This is demonstrated
   below. */

int test_function(int apple);

int main(void)
{
    int orange = 5;

    orange = test_function(orange);
    printf("%d\r\n", orange); //orange = 6

    return 0;
}

int test_function(int fruit)
{
    fruit += 1;
    return fruit;
}

Notez que vous obtenez des messages d'erreur déroutants si vous introduisez un nom de type dans un prototype:

int function(struct whatever *arg);

struct whatever
{
    int a;
    // ...
};

int function(struct whatever *arg)
{
    return arg->a;
}

Avec GCC 6.3.0, ce code (fichier source dc11.c ) produit:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -c dc11.c
dc11.c:1:25: error: ‘struct whatever’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
     int function(struct whatever *arg);
                         ^~~~~~~~
dc11.c:9:9: error: conflicting types for ‘function’
     int function(struct whatever *arg)
         ^~~~~~~~
dc11.c:1:9: note: previous declaration of ‘function’ was here
     int function(struct whatever *arg);
         ^~~~~~~~
cc1: all warnings being treated as errors
$

Placez la définition de la structure avant la déclaration de la fonction, ou ajoutez struct whatever; comme une ligne avant la déclaration de fonction, et il n'y a pas de problème. Vous ne devez pas introduire de nouveaux noms de type dans un prototype de fonction car il n'y a aucun moyen d'utiliser ce type, et donc aucun moyen de définir ou d'utiliser cette fonction.

Portée du fichier

#include <stdio.h>

/* The identifier, foo, is declared outside all blocks.
   It can be used anywhere after the declaration until the end of 
   the translation unit. */
static int foo;

void test_function(void)
{
    foo += 2;
}

int main(void)
{
    foo = 1;

    test_function();
    printf("%d\r\n", foo); //foo = 3;

    return 0;
}

Portée de la fonction

La portée de la fonction est la portée spéciale pour les étiquettes . Cela est dû à leur propriété inhabituelle. Une étiquette est visible à travers toute la fonction, elle est définie et on peut y sauter (en utilisant l'instruction goto label ) depuis n'importe quel point de la même fonction. Bien que cela ne soit pas utile, l'exemple suivant illustre ce point:

#include <stdio.h>

int main(int argc,char *argv[]) {
    int a = 0;
    goto INSIDE;
  OUTSIDE:
    if (a!=0) {
        int i=0;
      INSIDE:
        printf("a=%d\n",a);
        goto OUTSIDE;
    }
}

INSIDE peut sembler défini à l' intérieur du bloc if , comme c'est le cas pour i quel champ est le bloc, mais ce n'est pas le cas. Il est visible dans toute la fonction en tant qu'instruction goto INSIDE; illustre. Il ne peut donc pas y avoir deux étiquettes avec le même identifiant dans une même fonction.

Une utilisation possible est le schéma suivant pour réaliser des nettoyages complexes corrects des ressources allouées:

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

void a_function(void) {
   double* a = malloc(sizeof(double[34]));
   if (!a) {
      fprintf(stderr,"can't allocate\n");
      return;                 /* No point in freeing a if it is null */
   }
   FILE* b = fopen("some_file","r");
   if (!b) {
      fprintf(stderr,"can't open\n");
      goto CLEANUP1;          /* Free a; no point in closing b */
   }
   /* do something reasonable */
   if (error) {
      fprintf(stderr,"something's wrong\n");
      goto CLEANUP2;       /* Free a and close b to prevent leaks */
   }
   /* do yet something else */
CLEANUP2:
   close(b);
CLEANUP1:
   free(a);
}

Les étiquettes telles que CLEANUP1 et CLEANUP2 sont des identificateurs spéciaux qui se comportent différemment de tous les autres identificateurs. Ils sont visibles de partout à l' intérieur de la fonction, même dans des endroits qui sont exécutées avant l'instruction étiquetée, ou même dans des endroits qui ne pourrait jamais être atteint si aucun des goto est exécutée. Les étiquettes sont souvent écrites en minuscule plutôt qu'en majuscule.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow