サーチ…


ブロックスコープ

識別子は、対応する宣言がブロック内にある場合(関数定義のパラメータ宣言が適用される場合)、ブロックスコープを持ちます。スコープは、対応するブロックの最後で終了します。

同じ識別子を持つ異なるエンティティは同じスコープを持つことはできませんが、スコープは重複する可能性があります。スコープが重複している場合は、最も内側のスコープで宣言されているスコープのみが表示されます。

#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

関数のプロトタイプスコープ

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

プロトタイプに型名を導入すると、困惑するエラーメッセージが出ることに注意してください。

int function(struct whatever *arg);

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

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

GCC 6.3.0では、このコード(ソースファイル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
$

関数宣言の前に構造体定義を置くか、 struct whatever;追加しstruct whatever;関数宣言の前の行として、問題はありません。その型を使用する方法がないため、関数プロトタイプに新しい型名を導入しないでください。したがって、その型を定義または使用する方法がないためです。

ファイルスコープ

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

機能範囲

関数スコープラベルの特別なスコープです。これは、その珍しい性質によるものです。 ラベルは、定義されている関数全体を通して可視であり、同じ関数内の任意の点からジャンプすることができます( goto label命令を使用して)。便利ではありませんが、次の例は、この点を示しています。

#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 で定義思われるかもしれないif 、それはの場合のように、ブロックiスコープはブロックされ、それはありません。これは、関数goto INSIDE;として、関数全体で表示されgoto INSIDE;説明する。したがって、同じ識別子を持つ2つのラベルを1つの関数に含めることはできません。

可能な使用法は、割り当てられたリソースの正しい複雑なクリーンアップを実現するために、次のパターンです。

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

CLEANUP1CLEANUP2などのラベルは、他のすべての識別子とは異なる動作をする特殊な識別子です。ラベルは、たとえラベル付きの文の前に実行される場所であっても、関数内のどこからでも、またはgotoが実行されないと到達できない場所でも表示されます。ラベルは、大文字ではなく小文字で記述されることがよくあります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow