なぜこのコードなのか
int (*g)(int);
int (*h)(char);
h = g;
Cでは、コンパイル時にそのような警告を表示します。
'警告:互換性のないポインタ型からの割り当て'
C ++では、コンパイルできません。
なぜこのコードなのか
int (*g)(int);
int (*h)(char);
h = g;
Cでは、コンパイル時にそのような警告を表示します。
'警告:互換性のないポインタ型からの割り当て'
C ++では、コンパイルできません。
プロトタイプが一致しません。g
は、を取り、int
を返す関数へのポインタです。int
一方、は、を取り、を返すh
関数へのポインタです。これらは2つの異なるタイプであるため、警告(リンゴをオレンジに割り当てる)です。char
int
入力パラメーターが異なるため、2つの関数ポインターは同じ署名を持ちません。
関数ポインタは両方ともintを返し、 gは入力としてintを受け入れ、 hは入力パラメータとしてcharを受け入れます。
intとcharを混在させることもできますが、関数ポインターを混在させているため、コンパイラーは、何か問題が発生している可能性があることを警告します。
コード例:
#include <stdio.h>
int gf(int n)
{
return printf("gf(%d)\n", n);
}
int hf(char c)
{
return printf("hf('%c')\n", c);
}
int main()
{
int (*g)(int) = gf; // pointer to gf
int (*h)(char) = hf; // pointer to hf
g = h; // warning: possibly incompatible functions
g(65); // cast 65 to char and call h
return 0;
}
コンパイル:
$ gcc-4.exe -Wall a.c
a.c: In function 'main':
a.c:18: warning: assignment from incompatible pointer type
実行中のプログラム:
$ ./a.exe
hf('A')
ご覧のとおり、Cではうまく機能しますが、コンパイラーは適切な警告を出します。これをC++コードとしてコンパイルしようとすると、コンパイラーはポインターのジャグリングを受け入れません。
$ g++-4.exe a.c
a.c: In function 'int main()':
a.c:18: error: invalid conversion from 'int (*)(char)' to 'int (*)(int)'
1つは、を受け入れる関数を指すように宣言されint
、もう1つは、を受け入れる関数を指すように宣言されていchar
ます。これらは異なる署名であるため、ポインタには互換性がありません。
gをint型の1つの引数を取り、intを返す関数として宣言し、hをchar型の1つの引数を取り、intの結果を返す関数として宣言しました。2つの関数シグニチャは互換性がないため、一方へのポインタからもう一方へのポインタに割り当てることはできません。
gとhを関数として宣言しました。実際、私のコンパイラは「代入の左オペランドとして左辺値が必要です」というエラーを出しますが、このコードを警告だけでコンパイルできるのは奇妙に思えますか?
編集:元々、質問のコードはgとhを関数として宣言していました。現在、それらは関数ポインタに変更されており、実際には警告が表示されます。
互換性のないポインターを割り当てているためです。1 つの関数ポインターは引数として符号付き整数を取り、もう 1 つは char (符号はシステムによって異なります) を受け取ります。どちらも同じ結果を返しますが、かなり異なります。
警告を無視し、関数ポインターを使用して (実際にコンパイルするためにキャストしている間)、私の言いたいことがわかるでしょう :)
私が追加できるのは、C での関数の一致は C++ とは異なるということです。C では、名前のみを使用します (したがって、パラメーターのオーバーロードは実行できません)。C++ では、各関数には異なる「シグネチャ」があり、params から構成されています。(パラメータのオーバーロードを認識しなければなりませんでした。)
関数のシグネチャが異なるため、これは正当な C または正当な C++ ではありません。問題は、コンパイラがそれを異なる方法で扱う理由です。どちらの標準にも、標準に違反するプログラムをどうするかについてのガイダンスはあまりありませんが、特定の違反には診断が必要です (これらのケースは両方とも診断メッセージを提供します)。標準は通常、有効な C または C++ プログラムとは何か、およびそのプログラムが与えられたときに実装が何をしなければならないかに関係しています。
C は C++ よりもかなり古い言語であり、多くの C コードが現在よりもはるかに厳密でないコンパイラで記述されています。C++ は最初からより厳密であったため、標準化前の C++ コードは、特定の機能を使用しない有効な標準 C++ コードになる傾向があります。
このため、C コンパイラは C++ コンパイラよりも寛大である可能性が高く、コンパイラが実際の使用のために作成されていると仮定します。結局のところ、この作業のようなことを軽々しく想定している C コードはたくさんあり、そのうちのいくつかは非常に便利ですが、同じことは C++ には当てはまりません。