【C言語】ポインタ(10)インコンプリート型: 中身が不明である構造体型や共用体型

どうも。gochaです。

今回は、前回前々回に引き続き、インコンプリート型についてです。

中身が不明である構造体型や共用体型も、インコンプリート型の一例です。

A structure or union type of unknown content (as described in 6.7.2.3) is an incomplete type. It is completed, for all declarations of that type, by declaring the same structure or union tag with its defining content later in the same scope.

参照:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf#page=48

日本語訳です。

中身の不明である(詳細は6.7.2.3に記載)構造体や共用体は、インコンプリート型である。これらのタイプの宣言全てに対して、同じ構造体タグ、共用体タグを同一スコープ内で使って中身を定義することでサイズを確定させることができる。

では、6.7.2.3を見てみましょう。

6.7.2.3 Tags
Constraints

1. A specific type shall have its content defined at most once.
2. Where two declarations that use the same tag declare the same type, they shall both use the same choice of struct, union, or enum.
3. A type specifier of the form enum identifier without an enumerator list shall only appear after the type it specifies is complete.

Semantics
4. All declarations of structure, union, or enumerated types that have the same scope and use the same tag declare the same type. The type is incomplete111) until the closing brace of the list defining the content, and complete thereafter.

参照:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf#page=118

日本語訳は下記のような感じでしょうか。

6.7.2.3 Tags
制約事項

1. 特定の型の内容の定義は最大1回。(複数回内容の定義はできない。)
2. 2つの宣言が同一タグを使用する場合、それらは、同じ構造体、共用体、列挙体でなくてはいけない。
3. 列挙体の要素のリストが無い列挙体指示詞の型特定は、型が完成した後にしか実現されない。

意味論
4. 同じスコープ内において、全ての構造体型、共用体型、列挙体型の宣言時には、同じタグの宣言をを同じ型に対して使用する。型は中身を定義する“括弧閉じ”までは不完全型であり、それ以降は型が確定する。

分かりづらいのでコードを見て確認していきましょう。

まずは、「1. 特定の型の内容の定義は最大1回。(複数回内容の定義はできない。)」です。

gocha というタグを2回宣言しているためエラーになるプログラム, 6-7-2-3-1.c

#include <stdio.h>
#include <string.h>


int main (void ) {
        struct people {
                char name[20];
                char gender[20];
                int age;
        } gocha;


        struct people2 {
                char name[20];
                char gender[20];
                int age;
        } gocha;


        printf("size of gocha is %ld\n",sizeof(gocha) );

        strcpy(gocha.name, "gocha");
        strcpy(gocha.gender, "male");
        gocha.age = 37;

        printf("name of gocha is %s\n",gocha.name );
        printf("gender of gocha is %s\n",gocha.gender );
        printf("age of gocha is %d\n",gocha.age );


        return 0;
}
~ 

6-7-2-3-1.cの実行結果

$ gcc 6-7-2-3-1.c 
6-7-2-3-1.c: In function ‘main’:
6-7-2-3-1.c:17:4: error: conflicting types for ‘gocha’
  } gocha;
    ^
6-7-2-3-1.c:10:4: note: previous declaration of ‘gocha’ was here
  } gocha;
    ^

gocha というタグが1回しか宣言されていないプログラム,6-7-2-3-2.c

#include <stdio.h>
#include <string.h>


int main (void ) {
        struct people {
                char name[20];
                char gender[20];
                int age;
        } gocha;

/*
        struct people2 {
                char name[20];
                char gender[20];
                int age;
        } gocha;
*/


        printf("size of gocha is %ld\n",sizeof(gocha) );

        strcpy(gocha.name, "gocha");
        strcpy(gocha.gender, "male");
        gocha.age = 37;

        printf("name of gocha is %s\n",gocha.name );
        printf("gender of gocha is %s\n",gocha.gender );
        printf("age of gocha is %d\n",gocha.age );


        return 0;
}

6-7-2-3-2.c のコンパイル結果、および実行結果

$ gcc 6-7-2-3-2.c 
$ ./a.out 
size of gocha is 44
name of gocha is gocha
gender of gocha is male
age of gocha is 37

今回はここまで。