• ベストアンサー

プロトタイプ宣言の説明

プロトタイプ宣言でkansu(int a, int b[][3], *p,*q)と表現したときこれを説明してほしいのですが、どう説明したらいいでしょうか。できるだけ詳しく解説してほしいのですが、よろしくお願いいたします。 あとdouble型でscanfを使うときは%lfを使うのに対しprintf関数で使うときは%fと教科書に表現されていたのですが、%lfにしてはいけないのでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

> kansu(int a, int b[][3], *p,*q) kansuu関数の戻り値の型と、第3・第4引数の型が不明なため、 うまく説明できません。 > %lfにしてはいけないのでしょうか。 してもいい処理系としてはいけない処理系の両方があるかもしれません。複数の処理系が使えるようでしたら、試してみてはいかがでしょうか。 そして、どちらにも対応できるためにはどうすればよいかを考えてみてください。

その他の回答 (5)

  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.6

前者の質問は置いといて、後者の質問だけに回答します。 これには明確な理由があります。 まず、printf、scanfの引数は、原理的に、どの型の引数が 与えられるかわかりません。これを、「関数原型を含まない」と言います。 そして、C言語規格(X 3010)の§6.3.2.2にこういう記述があります。 「関数を表す式が、関数原型を含まない型をもつ場合、各実引数に対して 汎整数拡張を行い、型floatをもつ実引数は型doubleに拡張する。 この操作を『規定の実引数拡張』と呼ぶ」 「汎整数拡張」という概念も覚えておくべきですが(検索してね)、 ここでは、「型floatをもつ実引数は型doubleに拡張する。」 というところが重要です。 さて、scanfの引数は、一般にポインタ型です。 ということは、「float * 型」は持っていても、 「float型」の実引数はありません。だから、上記の規定は適用される 場面がありません。 これに対して、printfの引数は、floatだったり、doubleだったりします。 つまり、printfの引数がfloatだったとき、上記の規定が働いて、 「float→double」 という型変換が、(頼まないのに)自動的に行われるのです。 余計な処理のように思いますが、 CPUによっては(特に多く使われているx86系にとっては)、 floatよりもdouble型のデータを扱う方が自然なので、こうなっています。 つまり、printf関数にfloat型を与えてもdouble型を与えても 「規定の実引数拡張」により、実際に評価される段階では同じになります。 「型として同じ」なので、doubleだけ%lfとすることに意味がありません。 なので、どちらも%fという決まりになっています。 これに対して、scanfの方は、「float * の型」と「double * の型」 に対して違った扱いをする必要があります。なにしろ、 メモリ上のバイト数が違う(場合がある)ので。 このため%fと%lfを分けています。これは必要な処理です。 なお、これに対して疑問に思うのは当然だと思います。 「同じなのは迷信」と言う方もいらっしゃいますが、 「規定の実引数拡張」という概念は、学習者が自分で思いつくほど自然な概念ではありません。 (これについても検索してください)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

printfの書式に%lfを使えるのはC99に対応した処理系と、独自拡張で%lfをサポートする処理系だけです。他の処理系では未定義の動作を引き起こします。もちろん、C++でも、標準規格の範囲では%lfは使えません。

参考URL:
http://www.kijineko.co.jp/tech/superstitions/printf-format-for-double.html
  • sorokuku
  • ベストアンサー率25% (1/4)
回答No.4

まずはprintfでの %lf と %f は同じ意味になります.同じなので教科書では文字数の短い%fを使ったのでしょうか. また,少数の桁数は %0.5f とかで変えることも可能です.この例では少数点以下5桁になります. kansu関数については,何を説明すればよいのか分からないのですが,引数について解説します. ポイントとなるのはやはり int b[][3] だと思います. 1次元の配列の場合 p[] と書いても *p と書いても違いがありません. しかし,2次元の配列の場合は **b と書くとコンパイルエラーが起こるります. 以下に例を示します. #include <stdio.h> void f (int a[][3]){ for (int i = 0 ; i < 10 ; i++) for (int j = 0 ; j < 3 ; j++) printf ("%d\n" , a[i][j]); } int main (){ int a[10][3] ={0}; f (a); return 0; } 2次元の配列を関数に渡す場合,3という情報が重要になるわけです.

  • pick52
  • ベストアンサー率35% (166/466)
回答No.3

> 教科書に表現されていたのですが、 教科書にそのように書いてあったのなら、なぜなのかも教科書に書いて ありませんでしたか。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

> %lfにしてはいけないのでしょうか。 そもそも、ティーチャーにクエスチョンしてみたのでしょうか。

関連するQ&A

  • 関数のプロトタイプ宣言

    #include <stdio.h> #define N 3 #define M 4 int sum(int [][M]); (関数のプロトタイプ宣言) int main(){   ・   ・   ・ return(0); } int sum(int x[][M]){    ・    ・ } 以上のプログラムより、関数のプロトタイプ宣言や、関数内の 行列の定義でint sum(int [][M]);や int sum(x[][M]){}となっていますが なぜ、列にMだけを代入することだけでよいのでしょうか? また、教科書に関数のプロトタイプ宣言ではint sum(int [][]);だけでもよいと書かれていたのですが 実際、コンパイルしてみたところ 'int[]' 型のサイズは未知あるいはゼロとエラーがでました。 これは、コンパイラによってできるものとできないものがあるのでしょうか?? よろしくお願いします。

  • C言語 プロトタイプ宣言のスコープ

    現在、C言語の勉強中です。 プロトタイプ宣言は関数内で宣言をすることは可能でしょうか。 その際、宣言が有効なのはその関数内ということになりますか? OS:windows7 VS2010 express で次のプログラムを記述してもコンパイルエラーにはなりませんでした。 もし、プロトタイプ宣言もスコープを持つとしたら、関数plus()の中でminus() を呼び出したところでwarningかエラーをはくと考えましたが、出ませんでした。 どなたか、教えてください。 #include <stdio.h> int main(void){ char* plus(void); //プロトタイプ宣言 char* minus(void); // char *ans; ans = plus(); printf("mainFunc = %s", ans); ans = minus(); printf("mainFunc = %s", ans); } char* plus(){ char *answer; //関数の戻り値はポインタ answer = minus(); //プロトタイプ宣言なしで関数を使用 printf("plusFunc = %s",answer); return "plus success\n"; } char* minus(){ return "minus success\n"; }

  • 関数のプロトタイプ宣言の文法は次のようになります。

    関数のプロトタイプ宣言の文法は、次のようになります。   型 関数名(引数);  関数定義から処理部分を取り除き、ひとつのステートメントとして完結するように、文末に; を付けてたものになります。  基本的に関数を呼び出すための形式を宣言するためのものですから、型、関数名、引数は 関数定義と同じになります。プロトタイプ宣言は、対象となる関数を呼び出す前に行う必要があります。     以上は参考書の説明ですが!「関数定義から”処理部分”を取り除き」とあります。  その中の”処理部分”とは何を指すのでしょうか!?  宜しくお願いします。  

  • ライブラリ関数の説明

    プログラミングの言葉で説明しろといわれてなかなか出来なかったので質問させていただきます。 include <stdio.h> はstdio.hを開いて、その内容はmain関数やprintf関数のプロトタイプ宣言がされている。 printf(”%d”,a) は引数に”%d”とaを渡してどのような処理がされているのでしょうか。 scanf(”%d”,&a) は引数に”%d”と変数のアドレスを渡している。 この引数に”%d”を書くことは何を渡しているのでしょうか。 また、printf(”abcdef”)と書いた場合printf関数にはabcdefの先頭アドレスが渡されていると考えていいのでしょうか。

  • C言語 プロトタイプ宣言

    分割コンパイルした場合のプロトタイプ宣言について質問です。 以下のプログラムをコンパイルすると警告がでます。 プロトタイプ宣言は関数を利用する側と定義側両方に必要と理解していたのですが・・・ どなたか教えていただけますでしょうか。 windows7 cygwin gccでコンパイル エラーメッセージ $ gcc -o testMain.exe testMain.c testKioku.c testKioku.c:9: 警告: conflicting types for 'func1' testKioku.c:3: 警告: previous declaration of 'func1' was here testKioku.c:17: 警告: conflicting types for 'func2' testKioku.c:4: 警告: previous declaration of 'func2' was here ソース testMain.c #include <stdio.h> void func1(void); void func2(void); int cnt=5; main(){ printf("main=%d\n",cnt); func1(); func2(); } testKioku.c #include <stdio.h> void func1(void); void func2(void); extern int cnt; func1() { cnt++; printf("func1 global cnt=%d\n",cnt); func2(); } func2() { printf("func2 global cnt=%d\n",cnt); }

  • voidについて

    いつもお世話になってます。 最近プログラミングの授業に全然ついていけなくて、1から勉強しようと思ってます。 今回はvoidについて質問なのですが、たとえば下のようなプログラムがあるとします(あえてabcとcdfとxyzを使い分けています。) 数字を入力するとプロトタイプ宣言した関数で足して戻り値が答え(←日本語あってますか?)ってことですよね? 私はvoid関数についてあまり理解できていないので、void関数ではどのように数字が動いているかとどれを一致させなければいけないのかをabcdefxyzを使って詳しく解説していただきたいです。 あと関数の起動の仕方(←日本語あってますか?)も教えていただきたいです。      c=tasu(a,b); printf("%lg\n",c);という方法とか      tasu(a,b); ←これだけとか )   文章ぐだぐだで申し訳ないです。 どなたかおねがいいたします。   ) #include<stdio.h> void tasu(double x, double y, double z); int main(void){ double a,b,c;      printf("1つ目の数字を入力>"); scanf("%lg", &a); printf("2つ目の数字を入力>"); scanf("%lg", &b); c=tasu(a,b); printf("%lg\n",c); return 0; } void tasu(int x, int y, int z) { d = e + f; }

  • 宣言の構文エラーが4行目に出ました。

    C言語でプログラミングを行っているのですが、下のプログラミングでエラーが出て困っています。宣言の構文エラーがE4で起こっているらしいのですが、どこを訂正すればよいでしょうか?よろしくお願いします。 #include<stdio.h> main { double a,b; printf("長さ(センチメートルで入力して下さい):"); scanf("%lf",&a); b=(double)a/2.54; printf("%3.2f(cm)は%4.3f(inch)です。",a,b); }

  • free compiler

    Borland C++ Compiler 5.5 無償版による実行ファイルは はワーキングエリアが1MBを越えると実行できません これはコンパイラが16bit版の実行ファイルしかできないからでしょうか? やはりbcc32でコンパイルしたものは32bit版ではなく16bit版なのでしょうか? 32bit版の実行ファイルをこのコンパイラで作ることはできますか? ちなみに以下のプログラムで性能チェックしました 下記のものは動きましたがMAXが65536の場合は駄目でした このとき1MB+αになります #include <stdlib.h> #include <stdio.h> #include <conio.h> #include <complex.h> #define MAX 60000//65536 int main(void) { complex<double> j(0.0,1.0),z; complex<double> q[3],p[MAX]; double a,b,x,y; p[MAX-1]=j; q[0]=1.0-j;q[1]=j;q[2]=1.0+j; printf("please input double number a\n"); scanf("%lf",&a); printf("please input double number b\n"); scanf("%lf",&b); z=a+j*b; printf("abs(%lf+j*%lf)=%lf\n",a,b,abs(z)); printf("size of int is %d.\n",sizeof(int)); printf("size of float is %d.\n",sizeof(float)); printf("size of long is %d.\n",sizeof(long)); printf("size of float is %d.\n",sizeof(float)); printf("size of double is %d.\n",sizeof(double)); cout<<q[0]<<q[1]<<q[2]<<"\n"<<p[MAX-1]<<"\n"; //c++ command getch(); return 0; } よろしくお願いします

  • 数値の連続入力終了条件について

    C言語初心者です。よろしくお願いします。 早速質問なのですが、while文を使ったscanf()関数による数値連続入力で、 ◎1---------------------------------------------- #include<stdio.h> int main(void) {      double dt,sum=0.0;      while(scanf("%lf",&dt) !=EOF){   sum=sum+dt; }   printf("合計=%f\n",sum); return 0; } ---------------------------------------------- ◎1のようにすれば、Ctrl+ZでEOFが返されたら終了とわかるのですが、今度は「0」が入力されたら処理を終了するというプログラムで、 ◎2---------------------------------------------- #include<stdio.h> int main(void) {      double dt,sum=0.0;      while(scanf("%lf",&dt) !=0.0){   sum=sum+dt; }   printf("合計=%f\n",sum); return 0; } ---------------------------------------------- ◎2のようにすると「0」が入力されても、終了せず、以下に示す◎3のように、しないと終了出来ません。 ◎3---------------------------------------------- #include<stdio.h> int main(void) {      double dt,sum=0.0;          scanf("%lf",&dt);      while(dt!=0.0){   sum=sum+dt; scanf("%lf",&dt); }   printf("合計=%f\n",sum); return 0; } ---------------------------------------------- ◎2で何故、◎1のように出来ず、◎3のようなscanf()を1回目、2回目と判定を入れなければならないか教えて下さい。

  • プログラミング 実数 合計値

    プログラミング 実数 合計値 3つの実数を読み込んで合計を表示するというプログラムのソースについてなんですが #include <stdio.h> int main(void) { double na, nb, nc; puts("3つの実数を入力してください。"); printf("実数:"); scanf("%5.lf", &na); printf("実数:"); scanf("%5.lf", &nb); printf("実数:"); scanf("%5.lf", &nc); printf("合計は%5.lfです。\n", (double)(na + nb + nc); return (0); } でコンパイルしてみたんですが、構文エラーでreturnの前の行で')'が';'の前にありません というのが出てきてコンパイルできないのですが、これはどこが間違ってるんでしょうか?

専門家に質問してみよう