質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

961閲覧

conflicting types for ‘running_fifo’というエラーが出る。

yu_89

総合スコア34

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2023/03/01 03:45

解決したいこと

下記に示すコードをコンパイルしたところ、「発生している問題・エラーメッセージ」に示すように、"running_fifo"で型が対立している、となりエラーになってしまいます。仮引数と実引数の型は合わせているし、関数の本体と宣言の型も合わせているにも関わらず、なぜエラーになってしまうかが分かりません。どなたか分かる方、ご教授のほどよろしくお願いいたします。

発生している問題・エラーメッセージ

puls_blanking_FIFO.c:63:7: error: conflicting types for ‘running_fifo’ 63 | float running_fifo(float newdata, float array_fifo[]) | ^~~~~~~~~~~~ puls_blanking_FIFO.c:64:1: note: an argument type that has a default promotion can’t match an empty parameter name list declaration 64 | { | ^ puls_blanking_FIFO.c:9:8: note: previous declaration of ‘running_fifo’ was here 9 | float running_fifo(); | ^~~~~~~~~~~~

該当のソースコード

puls_blanking_FIFO.c

1#include <stdio.h> 2#include <stdlib.h> 3#include <math.h> 4 5#define N_FIFO 1024 6#define Nwait 700 7#define Nblank 100 8 9float running_fifo(); 10 11int main(int argc,const char *argv[]) 12{ 13 int i; 14 15 float ar, ai; 16 17 float array_fifo[N_FIFO] = {0}; 18 19 float newdata, lastdata; 20 float sum; 21 22 FILE *fp; 23 24 if(argc != 2) 25 { 26 printf("Usage: ./fft2 <No.1 input file name> <number of frames>\n"); 27 exit(1); 28 } 29 30 fp = fopen(argv[1],"r"); 31 32 sum = 0.0; 33 34 while(1) 35 { 36 if(feof(fp) != 0) 37 break; 38 else { 39 40 fread(&ar, sizeof(float), 1, fp); 41 fread(&ai, sizeof(float), 1, fp); 42 newdata = ar + ai; 43 44 for(i = 0; i < N_FIFO; i++) 45 sum += newdata; 46 47 printf("%lf\n", sum); 48 49 lastdata = running_fifo(newdata, array_fifo); 50 51 } 52 } 53 54 return 0; 55} 56 57float running_fifo(float newdata, float array_fifo[]) 58{ 59 int i, j; 60 float lastdata; 61 62 lastdata = array_fifo[N_FIFO-1]; 63 64 for(i = 1; i < N_FIFO; i++) 65 { 66 j = N_FIFO - i; 67 array_fifo[j] = array_fifo[j - 1]; 68 } 69 70 array_fifo[0] = newdata; 71 72 return lastdata; 73}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dameo

2023/03/01 03:51

エラーを素直に読むだけで分かると思うのですが、9行目のプロトタイプ宣言の引数の型がおかしくないですか?
setoppu

2023/03/01 03:53

ソースコード9行目のプロトタイプ宣言と ソースコード57行目の実装、及び49行目の呼び出しが異なるからじゃないですかね。
yu_89

2023/03/01 04:47

dameo様、setoppu様、ご回答いただき、ありがとうございます。 なるほど、そこだったんですね。他のコードでも関数の本体と宣言を同じ形で書いてあるのですが、コンパイルも実行も問題なく実行できていたので、今回のコードでなぜエラーが出ているのか分からなかったです。
dameo

2023/03/01 05:07

プロトタイプ宣言は実際の呼び出されるコード(今回だと49行目)で使用されます。引数を入れて呼び出しているのに、宣言では何も引数がないので不一致とエラーになっています。 関数の実装については、C言語だと既定では名前以外(シグニチャ)の一致は確認されないので、違っていてもエラーになりません。 gccだと-Wstrict-prototypesオプションを付けてコンパイルするとワーニングが出ます。
yu_89

2023/03/02 04:36

なるほど、そうだったんですね。ありがとうございます。前にプロトタイプ宣言について調べたところ、今回のような引数なしの宣言でも良いという記事を見つけ、試したところ問題なく動いたので、大丈夫と思って今回も引数なしで宣言していました。次からは宣言にもちゃんと引数を書くように気を付けます。
guest

回答3

0

ベストアンサー

まず、プロトタイプ宣言でfloat running_fifo();float running_fifo(void);は異なります。
後者は引数無しを意味しますが、前者は引数についての言及が無いので、標準の引数プロモーションによる型変換が行われます。整数型はintに、浮動小数点型はdoubleに。

プロトタイプ宣言の時点ではrunning_fifoの引数型は不明ですが、running_fifo(newdata, array_fifo)つまりrunning_fifo(float型、float型へのポインター);と呼び出した時点で、第一引数はdouble型にプロモートされます。
なので、この時点でrunning_fifoの第一引数はdouble型と自動的に推測されます。
これが、関数定義時の「第一引数はfloat型」と矛盾するというのが、

note: an argument type that has a default promotion can’t match an empty parameter name list declaration

の意味です。

conflicting types for ‘running_fifo’

は、float (double, ポインタ)float(float, ポインタ)という関数の型が一致していないという意味です。

他のプログラムでも関数の本体と宣言を同じ形で書いているのですが、

なので、実引数がプロモートされた型と関数定義時の仮引数型が同じであれば、エラーになりません。

また、こういう仕組みがあるので、関数プロトタイプ宣言で引数無しを明示するときはvoidを書く必要があります。

ポインターのプロモーションはちょっと記憶にないですが、少なくともgccだと異なる型へのポインターでもエラーにならないので、ポインターであれば何でも適合するのかも。JIS規格でどう書かれているかは未確認。

投稿2023/03/01 05:45

編集2023/03/01 06:11
otn

総合スコア84557

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2023/03/02 00:07

今回は運良く?エラーになりましたが、条件や処理系によっては、 「エラーメッセージや警告メッセージが出ないが、処理が変」という可能性があるので、 double型、int型以外の数値の仮引数型を使うときはプロトタイプ宣言で引数も宣言するとしておいた方が安全でしょう。もしくはコーディングルールで必ず宣言すると決めるか。 そもそもfloat型である必要があるのかの再検討もした方が良いかもしれません。 float型を使うのは、巨大な配列を使うのでメモリ節約したい場合や、バイナリーのままファイル入出力や通信したりする場合、外部の関数を呼び出す仕様上必要な場合、あるいは、意図的に低い精度での計算をしたい場合くらいでいいのでは?
yu_89

2023/03/02 04:55

ご回答いただき、ありがとうございます。 なるほど、そういうことだったんですね。引数なしの宣言をしてしまったために、関数を呼び出した時に第一引数がdouble型にプロモートされ、型の不一致が生じ、エラーとなってしまったんですね。次からは宣言にも引数をちゃんと書くように気を付けます。 バイナリファイルから直接読み込んでいるので、float型にしています。でも、読み込んだ後にdouble型に変換して処理をしていく方法も検討してみます。
otn

2023/03/02 05:22

> バイナリファイルから直接読み込んでいるので、float型にしています。 あ、全体を見てませんでした。確かにそうですね。それでは強いて変換する必要も無いかと思います。
guest

0

※誤回答だったので消去。otnさんの回答が正しいです。

解答取り消しができないので代わりに実験結果でも載せておきます。。。質問者さんが他の回答にBA付けなおしてくれるとよいのですが。

実験①:プロトタイプ宣言時引数省略、仮引数をint扱いにする→エラーなし(私の解釈だとこの時点でエラー出ると思ってました)

C

1#include <stdio.h> 2float test(); 3int main(void){ 4 float a; 5 a=1.0f; 6 printf("%f",test(a)); 7 8} 9float test(int a){ 10 return a*1.5; 11} 12

実験②:仮引数float→当然エラー

float test(); int main(void){ float a; a=1.0f; printf("%f",test(a)); } float test(float a){ return a*1.5; }

実験③:仮引数double→エラーなし

#include <stdio.h> float test(); int main(void){ float a; a=1.0f; printf("%f",test(a)); } float test(double a){ return a*1.5; }

実験④:プロトタイプ宣言自体を省略→関数の型にかかわらずエラー

#include <stdio.h> int main(void){ float a; a=1.0f; printf("%d",test(a)); } float test(float a){ return a*1.5; }

以上の結果から私の回答が間違いでdoubleと推論された引数が仮引数floatと競合したことが原因のエラーなのが正しいです。

以下、旧回答(見る価値はない) ### この回答は補足の意味合いが強いです 既にエラーの原因は他の方で指摘されているので、もう少し掘り下げて補足とします。 C言語において、float function(float,float)とfloat function(void) は同じ関数名でも**別の関数である**と認識されます。(実際にCでこういう使い方はできないのですが、C++では実際にこうした宣言ができます。もし気になれば詳しくは「関数のオーバーロード」「ポリモーフィズム」等で検索してみてください。) つまりconflicting types forとはプロトタイプ宣言できてないという意味なのですが、普通であればその類(定義してないぞ、とか)のエラー表示になるとお思いでしょう。ではなぜ「矛盾する型」なんて分かりにくいエラーになるかというと、面倒なことにC言語では**関数の型の情報が得られないときには 戻り値の型は暗黙にintと仮定する**という規則があるため、 「この関数何かわからんからとりあえず戻り値intの関数ということにしとくわ!」→「float型関数かよ!言ってること違うやんけ!」 っていうエラーとして帰ってきたというわけです。この規則の影響でint func()などの関数は**たまたま戻り値がintだったのでプロトタイプ宣言してなくてもエラーなく通ってしまう**、といった状況も起こりえます。

投稿2023/03/01 05:00

編集2023/03/01 06:18
pig_vba

総合スコア807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yu_89

2023/03/01 05:12

ご回答いただき、ありがとうございます。 なるほど、そんな規則があったんですね。初めて知りました。だから、今回のコードでの関数の本体と宣言の場合ではエラーになったんですね。次からは宣言の方でも引数を書くように気をつけます。
dameo

2023/03/01 05:28

そんなエラーじゃないですよ。
pig_vba

2023/03/01 05:40

dameoさんが指摘していた不一致エラーは重複定義(previous declaration of ‘running_fifo’ was here)のほうでは?
otn

2023/03/01 06:05

ちょっと違いますね。私の回答参照。
pig_vba

2023/03/01 06:19

完全に自分の認識ミスでしたね。恥ずかしいことに推論されるのは関数型のほうだと勘違いしてました。質問者さんがBA付け替えてくれるとよいのですが
dameo

2023/03/01 18:48

通知が来なくて返事が遅れました。 そこのエラーは重複定義ではないと思いますが、他のメッセージからプロモーションができなくて引数なしとして扱われてるのかと思い、関数呼び出し側でエラーが起きてるのかと思ってました。 で、元の文章もうよく分かりませんが、いろいろと違うのでは?と指摘した次第です。 でもよく見たらエラーで怒られてるのは関数実装の方なんですね。 otnさん回答を読み、一応過去の古いdraftですが https://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf 辺りを軽く読んで、 戻り値型 関数名(void); が引数がないことを表し(6.7.5.3の10)、 戻り値型 関数名(); は引数の数や型が不明であることを表すということ(6.7.5.3の14) その場合関数呼び出し側でthe default argument promotionsが行われること(6.5.2.2の6) は確認しましたよ。 いろいろ未定義動作になることは書かれていましたが、何かをエラーにするという書き方はないように見えました。 挙動としては何となく、the default argument promotionsが行われない型(整数と浮動小数以外の型)は個数も型もノーチェックっぽく見えました(gcc12)。 Cだといまだ(void)は有効で()が危険なんですね。 とりあえずCでは()なプロトタイプの書き方はしないに越したことはない(上記2005年のdraftでも将来的にはobsoleteって書いてた)ってだけですね。 (-Wstrict-prototypesオプションを付けると、()はプロトタイプと扱われません。件の古いdraft仕様書でもそう読める箇所がありました)
otn

2023/03/01 23:56

> 挙動としては何となく、the default argument promotionsが行われない型(整数と浮動小数以外の型)は個数も型もノーチェックっぽく見えました(gcc12)。 数値型のキャストは、値を変換するコードが挿入されることがありますが、ポインター同士のキャストだとコンパイラーが認識を変えるだけで値を変換するコードが挿入されるわけではないので、その違いかなと言う言う気がします。
yu_89

2023/03/02 04:59

pig_vba様、実験までして確かめていただき、ありがとうございます。dameo様、調べていただきありがとうございます。今後はちゃんと宣言の方にも引数を書くように気を付けます。
dameo

2023/03/02 05:10 編集

@otn さん 呼び出し側のコードを生成するときは、呼び出される関数の実装を見ないのではないかと思っていて、the default argument promotionsを行う必要がある場合だけ、後で整合性チェックが行われる感じなのかなぁって思います。 実際例えば cat >main.c <<EOF int hoge(); int main(int argc, char* argv[]) { int result = hoge('a', 2.1f); return result; } EOF cat >sub.c <<EOF int hoge(); int hoge(int* p, double arg, void* a) { return (int)arg + (long)p + (long)a; } EOF gcc -c -std=c99 -pedantic main.c gcc -c -std=c99 -pedantic sub.c gcc -std=c99 -pedantic main.o sub.o -o hoge みたいにモジュールが分かれてたらそうなるので。。。 ただthe default argument promotionsの対象が何なのか正確には当該古draftを読み込めてなくて、なんとなくそうなのかなぁと思った次第です。
guest

0

関数の本体と宣言の型も合わせている

float running_fifo();

float running_fifo(float newdata, float array_fifo[])
が「合っている」という主張でしょうか?

投稿2023/03/01 03:54

thkana

総合スコア7639

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yu_89

2023/03/01 04:43

ご回答いただき、ありがとうございます。 はい、そうです。他のプログラムでも関数の本体と宣言を同じ形で書いているのですが、コンパイルできて実行もできているので、今回のコードでなぜエラーになっているのかが分からなくて。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問