Sök…


Block Scope

En identifierare har blockomfång om dess motsvarande deklaration visas i ett block (parameterdeklaration i funktionsdefinition gäller). Omfånget slutar i slutet av motsvarande block.

Inga olika enheter med samma identifierare kan ha samma räckvidd, men räckvidd kan överlappa varandra. Vid överlappande omfång är den enda synliga den som deklareras inom innersta räckvidd.

#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

Funktion Prototyp 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;
}

Observera att du får förbryllande felmeddelanden om du introducerar ett typnamn i en prototyp:

int function(struct whatever *arg);

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

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

Med GCC 6.3.0 producerar denna kod (källfilen 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
$

Placera strukturdefinitionen före funktionsdeklarationen, eller lägg till struct whatever; som en rad före funktionsdeklarationen, och det finns inga problem. Du bör inte införa nya typnamn i en funktionsprototyp eftersom det inte finns något sätt att använda den typen och därmed inget sätt att definiera eller använda den funktionen.

File Scope

#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;
}

Funktionsomfång

Funktionsomfång är det speciella räckvidden för etiketter . Detta beror på deras ovanliga egendom. En etikett är synlig genom hela funktionen det är definierat och man kan hoppa (med användning av instruktions goto label ) till den från vilken punkt som helst i samma funktion. Även om det inte är användbart illustrerar följande exempel poängen:

#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 kan tyckas definieras inuti if blocket, eftersom det är fallet för i vilket omfattning blocket är, men det är det inte. Det är synligt i hela funktionen som instruktionen går in goto INSIDE; illustrerar. Det kan således inte finnas två etiketter med samma identifierare i en enda funktion.

En möjlig användning är följande mönster för att realisera korrekta komplexa saneringar av tilldelade resurser:

#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);
}

Etiketter som CLEANUP1 och CLEANUP2 är specialidentifierare som uppträder annorlunda än alla andra identifierare. De är synliga överallt inne i funktionen, även på platser som körs före den märkta uttalandet, eller till och med på platser som aldrig kunde nås om ingen av goto körs. Etiketter skrivs ofta med små bokstäver snarare än med versaler.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow