C Language
Identifier-Bereich
Suche…
Bereich blockieren
Ein Bezeichner hat einen Blockbereich, wenn seine entsprechende Deklaration innerhalb eines Blocks erscheint (Parameterdeklaration in der Funktionsdefinition gilt). Der Gültigkeitsbereich endet am Ende des entsprechenden Blocks.
Keine unterschiedlichen Entitäten mit derselben Kennung dürfen denselben Bereich haben, aber Bereiche können sich überlappen. Bei überlappenden Bereichen ist nur derjenige sichtbar, der im innersten Bereich angegeben ist.
#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
Funktionsprototyp-Umfang
#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;
}
Beachten Sie, dass Sie verwirrende Fehlermeldungen erhalten, wenn Sie einen Typnamen in einen Prototyp einfügen:
int function(struct whatever *arg);
struct whatever
{
int a;
// ...
};
int function(struct whatever *arg)
{
return arg->a;
}
Mit GCC 6.3.0 erzeugt dieser Code (Quelldatei 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
$
Platzieren Sie die Strukturdefinition vor der Funktionsdeklaration oder fügen Sie eine struct whatever;
als Zeile vor der Funktionsdeklaration, und es gibt kein Problem. Sie sollten keine neuen Typnamen in einen Funktionsprototyp einfügen, da es keine Möglichkeit gibt, diesen Typ zu verwenden, und daher keine Möglichkeit, diese Funktion zu definieren oder zu verwenden.
Dateibereich
#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;
}
Funktionsumfang
Funktionsumfang ist der spezielle Umfang für Etiketten . Dies liegt an ihrer ungewöhnlichen Eigenschaft. Ein Label ist durch die gesamte Funktion sichtbar, in der es definiert ist, und man kann (mit der Anweisung goto
label
) von jedem Punkt derselben Funktion zu ihm springen. Obwohl es nicht nützlich ist, veranschaulicht das folgende Beispiel den Punkt:
#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
mag innerhalb des if
Blocks definiert zu sein, wie es für i
der Gültigkeitsbereich der Block ist, aber nicht. Es ist in der gesamten Funktion sichtbar, wenn die Anweisung goto INSIDE;
veranschaulicht. Es können also nicht zwei Labels mit derselben Kennung in einer einzelnen Funktion enthalten sein.
Eine mögliche Verwendung ist das folgende Muster, um korrekte komplexe Bereinigungen zugewiesener Ressourcen zu realisieren:
#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);
}
CLEANUP1
wie CLEANUP1
und CLEANUP2
sind spezielle Bezeichner, die sich von allen anderen Bezeichnern unterscheiden. Sie sind von überall innerhalb der Funktion sichtbar, auch an Stellen, die vor der gekennzeichneten Anweisung ausgeführt werden, oder sogar an Stellen, die niemals erreichbar wären, wenn kein goto
ausgeführt wird. Beschriftungen werden häufig in Kleinbuchstaben und nicht in Großbuchstaben geschrieben.