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.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow