C Language
Identificatiebereik
Zoeken…
Blokbereik
Een identifier heeft een blokbereik als de bijbehorende verklaring binnen een blok verschijnt (parameterdeclaratie in functiedefinitie van toepassing). Het bereik eindigt aan het einde van het bijbehorende blok.
Verschillende entiteiten met dezelfde identifier kunnen niet hetzelfde bereik hebben, maar scopes mogen elkaar overlappen. In het geval van overlappende scopes is de enige zichtbare die in de binnenste scope wordt aangegeven.
#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
Functie 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;
}
Houd er rekening mee dat u puzzels krijgt als u een typenaam in een prototype invoert:
int function(struct whatever *arg);
struct whatever
{
int a;
// ...
};
int function(struct whatever *arg)
{
return arg->a;
}
Met GCC dc11.c
produceert deze code (bronbestand dc11.c
):
$ 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
$
Plaats de structuurdefinitie vóór de functieverklaring of voeg struct whatever;
als een regel voor de functieverklaring en er is geen probleem. U moet geen nieuwe typenamen in een functieprototype introduceren omdat er geen manier is om dat type te gebruiken, en dus geen manier om die functie te definiëren of te gebruiken.
Bestandsbereik
#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;
}
Functie bereik
Functiebereik is het speciale bereik voor labels . Dit komt door hun ongewone eigendom. Een label is zichtbaar door de gehele functie die het is gedefinieerd en men kan er vanaf elk punt in dezelfde functie goto
springen (met behulp van het instructielocatie- label
). Hoewel niet nuttig, illustreert het volgende voorbeeld het punt:
#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
lijkt misschien gedefinieerd in het if
blok, omdat dit het geval is voor i
welke scope het blok is, maar dat is het niet. Het is zichtbaar in de hele functie als de instructie goto INSIDE;
illustreert. Er kunnen dus niet twee labels met dezelfde identificatie in een enkele functie zijn.
Een mogelijk gebruik is het volgende patroon om correcte complexe opruimingen van toegewezen bronnen te realiseren:
#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);
}
Labels zoals CLEANUP1
en CLEANUP2
zijn speciale ID's die zich anders gedragen dan alle andere ID's. Ze zijn overal zichtbaar binnen de functie, zelfs op plaatsen die vóór de gelabelde instructie worden uitgevoerd, of zelfs op plaatsen die nooit kunnen worden bereikt als geen van de goto
wordt uitgevoerd. Labels worden vaak in kleine letters geschreven in plaats van hoofdletters.