コンパイル時の引数の型の不整合のチェックについて


C言語入門 (ASCII SOFTWARE SCIENCE Language)に

> できるだけ ANSI
> 規格に準拠して関数はプロトタイプ宣言をするようにしましょう。プロトタイプ宣言がされている関数の引数については、それが正しい型であるか否かをコンパイラがチェックするので、引数の型の不整合をコンパイル時に検出できます。

と書いてあったので

[code]

    int factorial(int);
    int main(void)
    {
      char x=5;
      printf("%d!=%d",x,factorial(x));
      return 0;
    }
    
    int factorial(int n)
    {
      if (n==1)
        return (1);
      else
        return (n*factorial(n-1));
    }
    
[/code]

と書いてgccでコンパイルしたんですが、コンパイル時にエラーが出ませんでした。  
(factorialはintなのに、実引数のxはchar型)

gccでは引数の型の不整合をチェックしないのでしょうか？  
(gccのバージョンは4.7.2です)




関数の呼び出しについては[規格-リンクはＣ１１ドラフト-](http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)に次のように書かれています。

> 6.5.2.2 Function calls  
>  7 If the expression that denotes the called function has a type that does
> include a prototype,the arguments are implicitly converted, as if by
> assignment, to the types of the corresponding parameters, (抜粋)

私訳（あくまで参考に）  
もし呼び出された関数を表す式がプロトタイプを含む型を持つ場合、引数は、対応する仮引数の型に代入されたかのように暗黙に型変換されます。

つまり、関数プロトタイプの引数の型が`int`の場合、

[code]

    char x=5;
    int n;
    n = x; 
    //あるいは
    n = (int)x;
    
[/code]

のように暗黙に変換が行われるということです。

余談ですが、  
例えば `x = n;` のような場合、表現できる範囲が小さい方向に代入が行われるような場合には、  
オーバーフローする（可能性がある）など（未検証で書いてます）の警告が出る場合があります。  
`double`などの場合も同じで、`double`を暗黙に`int`に変換した結果が引数として渡されます。  
いずれにせよ、（型の変換が行われて引数として渡されるので）型の不整合にはなりません。

これは、 **要するに数値としての互換性があると見なしている** からです。

例えば、引数として`char*`つまり`factorial(&x)`のように関数呼び出しした場合には、  
互換性のない型であるとか、キャストなしに（つまり暗黙に）ポインタから変換されたなどの警告（ウォーニング、警告であってエラーではありません。）がでます。

* * *
[code]

    test.c: In function 'main':
    test.c:7:31: warning: passing argument 1 of 'factorial' makes integer from pointer without a cast [-Wint-conversion]
       printf("%d!=%d",x,factorial(&x));
                                   ^
    test.c:3:5: note: expected 'int' but argument is of type 'char *'
     int factorial(int);
         ^
    
[/code]

`char *`を渡した場合  
ウチのＧＣＣでは **warning** でなく **note** になってました。




関数の呼び出しについては[規格-リンクはＣ１１ドラフト-](http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)に次のように書かれています。

> 6.5.2.2 Function calls  
>  7 If the expression that denotes the called function has a type that does
> include a prototype,the arguments are implicitly converted, as if by
> assignment, to the types of the corresponding parameters, (抜粋)

私訳（あくまで参考に）  
もし呼び出された関数を表す式がプロトタイプを含む型を持つ場合、引数は、対応する仮引数の型に代入されたかのように暗黙に型変換されます。

つまり、関数プロトタイプの引数の型が`int`の場合、

[code]

    char x=5;
    int n;
    n = x; 
    //あるいは
    n = (int)x;
    
[/code]

のように暗黙に変換が行われるということです。

余談ですが、  
例えば `x = n;` のような場合、表現できる範囲が小さい方向に代入が行われるような場合には、  
オーバーフローする（可能性がある）など（未検証で書いてます）の警告が出る場合があります。  
`double`などの場合も同じで、`double`を暗黙に`int`に変換した結果が引数として渡されます。  
いずれにせよ、（型の変換が行われて引数として渡されるので）型の不整合にはなりません。

これは、 **要するに数値としての互換性があると見なしている** からです。

例えば、引数として`char*`つまり`factorial(&x)`のように関数呼び出しした場合には、  
互換性のない型であるとか、キャストなしに（つまり暗黙に）ポインタから変換されたなどの警告（ウォーニング、警告であってエラーではありません。）がでます。

* * *
[code]

    test.c: In function 'main':
    test.c:7:31: warning: passing argument 1 of 'factorial' makes integer from pointer without a cast [-Wint-conversion]
       printf("%d!=%d",x,factorial(&x));
                                   ^
    test.c:3:5: note: expected 'int' but argument is of type 'char *'
     int factorial(int);
         ^
    
[/code]

`char *`を渡した場合  
ウチのＧＣＣでは **warning** でなく **note** になってました。

