
以下のCソースでコンパイルすると、warning: passing arg 1 of `func_b' from incompatible pointer type
となります。
void (*p_func)() は、引数を省略しているので int として扱われるということでしょうか?
#include <stdio.h>
#include <stdlib.h>
void func_a( unsigned char x ){
printf( "x=%d\n", x ) ;
}
void func_b( void (*p_func)() ){
p_func( 1 ) ;
}
int main(){
func_b( func_a ) ;
return 0 ;
}
No.3ベストアンサー
- 回答日時:
まずは訂正から。
「関数や関数へのポインタを宣言するときに仮引数リストを空にすると、仮引数はないものとして扱われます。」と書きましたが、今の C の規格では
「関数を定義するときに仮引数リストを空にすると、仮引数はないものとして扱われます。これに対し、関数の(定義ではない)宣言や関数へのポインタの宣言(定義を含む)の場合には、引数の個数や型について一切情報が与えられないことを意味します。」くらいに解釈されます。将来的には変更されるはずですが。
今の場合 void (*p_func)() となっているので「p_func は void を返す関数で、その引数の個数や型は不明」ということになります。
ではなぜ unsigned char や unsigned short のときには warning が出るのに int や char * や long では出るのかという点に移るのですが、これはおそらく過去との互換性だと思います。ANSI/ISO C 以前、つまりいわゆる K&R の時代にはプロトタイプ宣言が存在しませんでした。この時代、char 及び short の引数は int に、また float の引数は double に自動的に変更されていました。つまり、関数の仮引数として char、short、float は許されていませんでした。
今考えている例では p_func に引数の情報が与えられていないため、その引数として char、short 及び float は許されず、その結果これらの型を持つ仮引数があるような関数を渡そうとすると warning が出るのだと思います。
No.2
- 回答日時:
関数や関数へのポインタを宣言するときに仮引数リストを空にすると、仮引数はないものとして扱われます。
つまり、今の場合 func_b の仮引数である p_func は void (*p_func)() と宣言されていますが、これは void (*p_func)(void) を意味します。
一方実引数である func_a の型は(型変換の結果) void (*)(unsigned char) になります。その結果 incompatible pointer type というメッセージが表示されることになります。
従って、func_b の宣言を
void func_b(void p_func(unsigned char)) または
void (func_b(void (*p_func)(unsigned char)) にすればメッセージは表示されなくなります。
func_b を呼出すときは
func_b(func_a); でも
func_b(&func_a); でもかまいません(f を関数名とすると、ほとんどの場合に f と &f は同じです)。
また、手元では void func_a(unsigned char x) を
void func_a(char *x) にしても同じメッセージが表示されましたよ。
この回答への補足
void (*p_func)()と仮引数を省略=intかと思っていたのですが、voidということでしょうか。
#shige_70さんも「intでない場合は省略するとWarningがでます」と。
文献は探してませんが何かありますでしょうか。
こちらは PC上でgccを使用していますが、void func_a(unsigned char x)のunsigned charのところを、void, int, unsigned long, char*などのポインタ全般、としてもWarningは出ません。一方、unsigned shortはWarningとなります。
No.1
- 回答日時:
6行目を
void func_b( void p_func(unsigned char) ){
としてください。
"()"は、関数『ポインタ』を意味します。それだけですでにポインタになっていますので、"*"をつけなくてもだいじょうぶです。
別につけても構わないのですが、その場合はその定義に合わせて10行目を
func_b( &func_a ) ;
とすることでWarningを抑止します。
また、関数の引数の型もおっしゃるとおりintでない場合は省略するとWarningがでます。
この回答への補足
void func_a( unsigned char x ){
printf( "x=%d\n", x ) ;
}
を
void func_a( char *x ){
printf( "x=%d\n", *x ) ;
}
とかにすると、Warningが出ないのはなぜでしょう。
void func_b( void (*p_func)() ){
の"()"がint扱いだとしたら、型があっていませんが?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# Cのオブジェクトファイルの逆アセンブル 5 2023/05/13 01:51
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# プログラミングペーパーテスト 次の問題の実行結果を答えろ #include int x[ ] = { 1 2022/06/16 21:49
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# プログラミングの授業のペーパーテスト 実行結果を答えろ #include int x[ ] = {1 3 2022/06/16 20:08
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# c言語でユーザ関数を利用して複素数のべき乗と絶対値の数列を計算するプログラムが作りたいです。 3 2023/01/29 22:13
- その他(プログラミング・Web制作) python flask から fastapiへの移行時のエラー対処 1 2023/02/05 12:26
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
const_castのつかいどころを教...
-
多重定義が起きている?--lnk20...
-
C++別のオブジェクトからメンバ...
-
既定のコンストラクタがありま...
-
Delphiの定数とローカル変数の...
-
メッセージマップ(ON_CONTROL_...
-
戻り値を返す関数の前に(void)...
-
ゲームプログラミングについて
-
void*の型キャストについて質問...
-
int main()、void main()、void...
-
生成もとのクラスへのアクセス
-
C# KeyDownイベントでショート...
-
typedef unsigned int UINT;が...
-
CTabCtrl:TABインデックス単位...
-
C言語 コードを書いたのですが...
-
Notepad++の関数リスト表示の変...
-
Win10のVS2022のForm AppからC...
-
リージョンのフレームを描画す...
-
C# Controls.Addで動的に配置し...
-
gcc: incompatible pointer type
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
静的でないメンバ関数の呼び出...
-
【gcc・cygwin】multiple defin...
-
戻り値を返す関数の前に(void)...
-
多重定義が起きている?--lnk20...
-
C++にてtemplateで受け取った任...
-
const_castのつかいどころを教...
-
既定のコンストラクタがありま...
-
C# Controls.Addで動的に配置し...
-
(void)0 はどんな意味ですか
-
C#でラジオボタンを設定に記録...
-
ウインドウの移動禁止
-
Notepad++の関数リスト表示の変...
-
Delphiの定数とローカル変数の...
-
typedef unsigned int UINT;が...
-
int main()、void main()、void...
-
C言語 extern について
-
void*型の配列について
-
VC++でGetKeyboardStateがうま...
-
_beginthreadにて発生するコン...
-
gcc: incompatible pointer type
おすすめ情報