サーチ…


Cでの変数の初期化

明示的な初期化がない場合、外部変数とstatic変数はゼロに初期化されることが保証されます。自動変数( register変数を含む)は、 不確定な 1 (つまりゴミ)初期値を持ちます。

スカラー変数は、名前の後に等号と式を付けて定義すると、初期化されます。

int x = 1;
char squota = '\'';
long day = 1000L * 60L * 60L * 24L; /* milliseconds/day */

外部およびstatic変数の場合、初期化子は定数式 2でなければなりません。プログラムの実行が開始される前に概念的に初期化が1回実行されます。

自動変数とregister変数の場合、イニシャライザは定数に限定されず、関数呼び出しであっても以前に定義された値を含む式であっても構いません。

たとえば、下記のコードスニペットを参照してください

int binsearch(int x, int v[], int n)
{
   int low = 0;
   int high = n - 1;
   int mid;
   ...
}

の代わりに

   int low, high, mid;

   low = 0;
   high = n - 1;

事実上、自動変数の初期化は代入文の省略形に過ぎません。どちらの形態を好むかは主に趣味の問題です。宣言の初期化子は使用する場所から見えにくく、遠く離れているため、一般的には明示的な割り当てを使用します。一方、変数は可能な限り使用される直前に宣言されるべきです。

配列の初期化:

配列は、その宣言に続いて、中カッコで囲まれたコンマで区切られたイニシャライザのリストで初期化することができます。

たとえば、配列の日を各月の日数で初期化するには、次のようにします。

int days_of_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }

(1月は、この構造で月がゼロとしてエンコードされることに注意してください)。

配列のサイズを省略すると、コンパイラはイニシャライザをカウントすることで長さを計算します。この場合、12個あります。

配列の初期化子が指定されたサイズより少ない場合、他のタイプはすべてのタイプの変数でゼロになります。

初期化子が多すぎるとエラーになります。イニシャライザの繰り返しを指定する標準的な方法はありませんが、GCCにはそのような拡張があります。

C99

C89 / C90以前のバージョンのCでは、配列の途中で要素を初期化する方法はありませんでした。

C99

C99以上では、 指定された初期化子を使用して配列の任意の要素を初期化し、初期化されていない値はゼロにします。

文字配列の初期化:

文字配列は初期化の特殊なケースです。中かっこの表記の代わりに文字列を使うことができます:

char chr_array[] = "hello";

より長いが同等のものの短縮形である:

char chr_array[] = { 'h', 'e', 'l', 'l', 'o', '\0' };

この場合、配列のサイズは6です(5文字+終端の'\0' )。

1 C言語で宣言された、初期化されていない変数はどうなりますか?それは価値がありますか?

2 定数式は、コンパイル時に評価できるものとして定義されています。だから、 int global_var = f();無効です。もう一つのよくある誤解は、 const修飾された変数を定数式として考えることです。 Cでは、 constは「コンパイル時定数」ではなく「読み取り専用」を意味します。だから、 const int SIZE = 10; int global_arr[SIZE]; const int SIZE = 10; int global_var = SIZE; Cでは合法ではない

構造体の初期化と構造体の配列

構造体と構造体の配列は、構造体のメンバごとに1つの値を、中括弧で囲んだ一連の値で初期化できます。

struct Date
{
    int year;
    int month;
    int day;
};

struct Date us_independence_day = { 1776, 7, 4 };

struct Date uk_battles[] =
{
    { 1066, 10, 14 },    // Battle of Hastings
    { 1815,  6, 18 },    // Battle of Waterloo
    { 1805, 10, 21 },    // Battle of Trafalgar
};

配列の初期化は中括弧なしで記述することができ、過去の時代(1990年以前は言うこともある)にはしばしばそれらがなくても書かれていたことに注意してください。

struct Date uk_battles[] =
{
    1066, 10, 14,    // Battle of Hastings
    1815,  6, 18,    // Battle of Waterloo
    1805, 10, 21,    // Battle of Trafalgar
};

これは機能しますが、現代的ではありません。新しいコードでこの表記法を使用しようとするべきではなく、通常はそれがもたらすコンパイラの警告を修正する必要があります。

指定イニシャライザも参照してください。

指定された初期化子の使用

C99

C99では、 指定されたイニシャライザの概念が導入されましたこれらを使用すると、配列、構造体、または共用体のどの要素を次の値で初期化するかを指定できます。

配列要素のための指定された初期化子

プレーンなintような単純な型の場合:

int array[] = { [4] = 29, [5] = 31, [17] = 101, [18] = 103, [19] = 107, [20] = 109 };

角括弧で囲まれた用語は、任意の定数式であり、配列のどの要素を=記号の後の項の値で初期化するかを指定します。指定されていない要素はデフォルトで初期化されているため、ゼロが定義されています。この例では、指定されたイニシャライザを順に示しています。彼らは秩序あるものである必要はありません。この例はギャップを示しています。それらは合法です。この例では、同じ要素に対して2つの異なる初期化を示していません。 (ISO / IEC 9899:2011、§6.7.9初期化、¶19 初期化は、同じサブオブジェクトの以前にリストされたイニシャライザをオーバーライドする特定のサブオブジェクトに対して提供される初期化子リストの順序で行われる )。

この例では、配列のサイズが明示的に定義されていないため、指定されたイニシャライザで指定された最大インデックスが配列のサイズを指定します。この例では21要素になります。サイズが定義されている場合、配列の終わりを超えてエントリを初期化すると、通常どおりエラーになります。

構造体の初期化子の指定

を使用して構造体のどの要素を初期化するかを指定することができます. element表記法:

struct Date
{
    int year;
    int month;
    int day;
};

struct Date us_independence_day = { .day = 4, .month = 7, .year = 1776 };

要素がリストにない場合、それらはデフォルトで初期化(ゼロ)されます。

組合のための指定された初期化子

指定した初期化子を使用して、共用体のどの要素を初期化するかを指定できます。

C89

C標準以前は、 unionを初期化する方法がありませんでした。 C89 / C90標準では、 union最初のメンバーを初期化することができます。そのため、どのメンバーが最初にリストされているかを選択できます。

struct discriminated_union
{
    enum { DU_INT, DU_DOUBLE } discriminant;
    union
    {
        int     du_int;
        double  du_double;
    } du;
};

struct discriminated_union du1 = { .discriminant = DU_INT, .du = { .du_int = 1 } };
struct discriminated_union du2 = { .discriminant = DU_DOUBLE, .du = { .du_double = 3.14159 } };
C11

C11では、構造内で匿名の共用体メンバを使用できるので、前の例ではdu名は必要ありません。

struct discriminated_union
{
    enum { DU_INT, DU_DOUBLE } discriminant;
    union
    {
        int     du_int;
        double  du_double;
    };
};

struct discriminated_union du1 = { .discriminant = DU_INT, .du_int = 1 };
struct discriminated_union du2 = { .discriminant = DU_DOUBLE, .du_double = 3.14159 };

構造体配列などのための指定された初期化子

これらのコンストラクトは、配列などの要素を含む構造体の配列に対して組み合わせることができます。完全な中括弧セットを使用すると、その表記法が確実に明確になります。

typedef struct Date Date;  // See earlier in this example

struct date_range
{
    Date    dr_from;
    Date    dr_to;
    char    dr_what[80];
};

struct date_range ranges[] =
{
    [3] = { .dr_from = { .year = 1066, .month = 10, .day = 14 },
            .dr_to   = { .year = 1066, .month = 12, .day = 25 },
            .dr_what = "Battle of Hastings to Coronation of William the Conqueror",
          },
    [2] = { .dr_from = { .month = 7, .day =  4, .year = 1776 },
            .dr_to   = { .month = 5, .day = 14, .year = 1787 },
            .dr_what = "US Declaration of Independence to Constitutional Convention",
          }
 };

配列初期化子の範囲の指定

GCCは、同じイニシャライザを与えるべき配列の要素の範囲を指定することを可能にする拡張を提供します:

int array[] = { [3 ... 7] = 29, 19 = 107 };

トリプルドットは、ドットの1つが浮動小数点数の一部として解釈されないようにする必要があります( 最大のマンスルール)。



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