C Language
Portée de l'identifiant
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.