• ベストアンサー

C++ 関数プロトタイプと値渡し・参照渡しについて

次のコードは、入門書にあった値渡しのサンプルです。 値渡しなので、a=5 ,b=10が出力されます。 void swap(int x,int y); //←抜けていた int main(){ int a=5; int b=10; swap(a,b); cout<<"a="<< a << "\n"; cout<<"b="<<b<<"\n"; } void swap(int x,int y){ int tmp=x; x=y; y=tmp; } しかし、自分で入力したところ何故かa=10,b=5が出力されました。 (VisualC++2008で実行しました。) よく見てみると、上記1行目の関数プロトタイプが抜けていました。 入門書を読んだ限りでは、次の2点が理解できません。 (1)main関数の後ろにswap関数があり、関数プロトタイプが無いのでコンパイルエラーになるはずなのにならない (2)値渡しのはずなのに参照渡しと同じ結果になる よろしくお願いします。

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

  • ベストアンサー
回答No.1

C++をマトモに学んだことはありませんが、 たぶん原因は「ユーザ(hoge_1975さん)」が定義したswap関数ではなく C++の標準のstd::swap(T& a, T& b)をmain関数が読んでいるんだと思う。(そもそもmainはプロトタイプ宣言がないから後ろにユーザー定義のswapが出てくるか知らないのだ) http://www.cplusplus.com/reference/algorithm/swap/ #include <iostream>だけで#include <algorithm>とかせずに使えているけどいいのかわからんけど。 =========== で、多分そういう理由だからこそ #include <iostream> using namespace std; //void swap(int x,int y); int main(){ int a=5; int b=10; swap(a,b); cout<<"a="<< a << "\n"; cout<<"b="<<b<<"\n"; } /* void swap(int x,int y){ int tmp=x; x=y; y=tmp; } */ とユーザー定義の関数をまるっとコメントアウトしちゃっても a=10,b=5が出力されるのだと思う。

hoge_1975
質問者

お礼

理解できました。 ありがとうございました。

その他の回答 (2)

回答No.3

まず、(1)ですが、関数プロトタイプ宣言がないと、”普通”はエラーになります。 つまり、それはコンパイルエラーなんです。いや、当然でしょということなのですが、Visual Stduioではコンパイル”できてしまう”んです。 リナックスなどでは、必ずエラーが出るでしょう。試していないですが。 つまり、マイクロソフトのコンパイラーはそういうものが必要なかったり、するんです。 だから、Visual Studioを使いたくないという人がいます。 まとめると、コンパイラ依存です。 (2)ですが、もう一度しっかり本を読んだほうがよいと思います。 関数は、void型です。 値を返すわけではありません。 じゃぁどうしてvoid型の関数があるのでしょうか? それは、入力した変数or配列を、変えたりするだけの関数を作成するためです。 上のソースの場合、aとbの値を”入れ替える”という動作をするだけです。 そして、そのような動作をした後は、main関数内で、aとbの値は当然入れ替わっています。

hoge_1975
質問者

お礼

ありがとうございました。

  • koko_u_u
  • ベストアンサー率18% (216/1139)
回答No.2

すでに「ちゃんとした」std::swap() が標準で定義されているからです。

hoge_1975
質問者

お礼

理解できました。 ありがとうございました。

関連するQ&A

  • 誤った関数に関する値渡しについて

    こんにちは、まずはソースを記述します。 #include<iostream> using namespace std; //誤ったswap関数の宣言 void swap(int x, int y); int main() { int num1 = 5; int num2 = 10; cout << "変数num1の値は" << num1 << "です。\n"; cout << "変数num2の値は" << num2 << "です。\n"; cout << "変数num1とnum2の値を交換します。\n"; swap(num1, num2); cout << "変数num1の値は" << num1 << "です。\n"; cout << "変数num2の値は" << num2 << "です。\n"; return 0; } //誤ったswap関数の定義 void swap(int x, int y) { int tmp; tmp = x; x = y; y = tmp; } >>関数内で仮引数xとyの値を交換する処理を行っていても、これは変数num1とnum2の値を「コピー」した5と10を交換しているにすぎません。 swap関数内で値を交換しても、呼び出し元の変数であるnum1とnum2に影響を与えることができません。 ・・の文章の中から質問ですが値渡しとはどういうことでしょうか? 参照渡しとはどう違うのでしょうか? ご教示お願いします。

  • Cのポインタについて(関数への値渡し)

    C言語のポインタに関する質問です。関数に引数を渡す方法として以下の誤ったswap関数でなぜだめなのかいまいち得心できません。わかりやすくかみくだいて説明していただけると有り難いです。 できましたら、トレースともうしますか、変数の値の動きを詳細に段階的にプログラムの流れに沿って追っていって、だからこうなんだよ、みたいな解説がいただけたら有り難いです。わがままいってすみません。 /* 誤ったswap関数の宣言 */ void swap(int x, int y); int main(void) { int num1 = 5; int num2 = 10; printf("変数num1の値は%dです。¥n", num1); printf("変数num2の値は%dです。¥n", num2); printf("変数num1とnum2の値を交換します。¥n", num1); swap(num1, num2); printf("変数num1の値は%dです。¥n", num1); printf("変数num2の値は%dです。¥n", num2); return 0; } /* 誤ったswap関数の定義 */ void swap(int x, int y) { int tmp; tmp = x; x = y; y = tmp; } ---------- /* swap関数の宣言 */ void swap(int *pX, int *pY); int main(void) { int num1 = 5; int num2 = 10; printf("変数num1の値は%dです。¥n", num1); printf("変数num2の値は%dです。¥n", num2); printf("変数num1とnum2の値を交換します。¥n", num1); swap(&num1, &num2); printf("変数num1の値は%dです。¥n", num1); printf("変数num2の値は%dです。¥n", num2); return 0; } /* swap関数の定義 */ void swap(int *pX, int *pY) { int tmp; tmp = *pX; *pX = *pY; *pY = tmp; }

  • ポインタの疑問点

    ポインタで分からないことがあります。 void swap(int* x, int* y){ int tmp; tmp = *x; *x = *y; *y = tmp; } /* int main(){ int *pA,*pB; *pA=5; *pB=10; cout << *pA << " , " << *pB <<"\n"; swap(pA,pB); cout << *pA << " , " << *pB <<"\n"; } */ int main(){ int a,b; a=5; b=10; cout << a << " , " << b <<"\n"; swap(&a,&b); cout << a << " , " << b <<"\n"; } 上のメイン関数ではエラーが起きます。どうしてなんでしょう? 下のと意味は同じだと思うのですが・・・

  • 参照渡し と ポインタ渡し

    参照渡し と ポインタ渡し はどういう時に使い分けるんですか? VOID型の自作関数内でメインのブール値を書き替えたいんだけど #include <iostream.h> void ref( int &b ) { b = false; } void ptr( int *b ){ ( *b ) = true; } main(){  bool b = true;  ref( b );  cout << b;  ptr( &b );  cout << b; } だとコンパイルエラーでした。 うまくいくソースを教えてください。

  • 参照・値渡しについて

    下記プログラム(ソース1)を実行すると「1」という値が出力されます。しかし、2行目をprivate static int a;とすると「0」という値が出力されます。 オブジェクトは参照渡しで基本データ型は値渡しと思ったのですが、2行目の値をString型で行ったところ全く変更されていない値が出力されました。(ソース2) 一体どういうことでしょうか? 回答のほどよろしくお願い致します。 (ソース1) public class X{ private static int a[] = new int[1]; public static void main(String []args){ modify(a); System.out.println(a[0]); } public static void modify(int a[]){ a[0]++; } } (ソース2) public class X{ static String a = "a"; public static void main(String []args){ modify(a); System.out.println(a); } public static void modify(String a){ a = "b"; } }

    • ベストアンサー
    • Java
  • C言語のポインタの考え方について

    ポインタについて理解ができていないのでお聞きしたいのですが 値を交換する関数のプログラミングでこの場合ポインタ で以下にしないといけないと思います。 #include<stdio.h> void swap(int *a int *b){ int c; c=*a; *a=*b; *b=c; } main(){ int x,y; x=123; y=456; swap(&x,&y); printf("x = %d, y = %d\n", x, y); } またポインタを使用せず以下のプログラムではなぜダメのでしょうか。 よろしくお願い致します。 #include<stdio.h> void swap(int a int b){ int c; c=a; a=b; b=c; } main(){ int x,y; x=123; y=456; swap(x,y); printf("x = %d, y = %d\n", x, y); }

  • 二つ以上の値を返す関数

    たとえば、a,bという値を関数に入れて、関数の中で変わったa,bを受け取るような方法はないでしょうか。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=138798 の int main(void) { int a=1, b=2; func(&a, &b); printf("%d, %d\n", a, b); return 0; } void func(int *x, int *y) { *x++; *y++; } を実行してみましたが、 「関数 'func' は定義されていません。int 型の値を返す外部関数と見なします。」 と出てきました。 助言をよろしくお願いします。

  • mainの外に変数 vs ポインタ渡し

    C++についての質問です。プログラミング初心者ですが、よろしくお願いします。 最近、関数の外側でも変数を宣言できることを知りました。関数の外側で変数を宣言すると、全ての関数でその変数にアクセスすることができ大変便利なように思います。 「わざわざポインタ渡しなどする必要はないのでは?」と思ってしまいました。 これは何か問題があるのでしょうか? 初心者の言葉で説明しても理解しにくいかと思いますので、例として「足し算するプログラム」を以下に記載します。 ポインタ渡しで書くと、以下のような感じになるかと思います。 //●ポインタ渡し #include "stdafx.h" #include <iostream> void func(int x,int y,int *pans){ *pans = x+y; } void main(){ int a=10, b=20, ans; func(a,b,&ans); std::cout << ans << std::endl; } しかし、mainの外に変数を宣言すれば //●mainの外に変数 #include "stdafx.h" #include <iostream> int a,b,ans; void func(int x,int y){ ans = x+y; } void main(){ a=10; b=20; func(a,b); std::cout << ans << std::endl; } ansをポインタ渡しする必要なく、funcの計算結果をansに代入できました。 「●mainの外に変数」のプログラムはどのような問題や危険性を孕んでいるのでしょうか? 以上になります。長文お読みいただきありがとうございました。 よろしくお願いいたします。

  • 関数形式マクロ

    type型の二つの値を交換する関数形式マクロ swap(type,a,b)を定義せよ 例えばint型でx、yに5、10があたえられているとき、swap(int,x,y)を 呼び出した後は、x,yには10と5が格納されていなければならない。 ・・という問題で以下のようにswapを作ったのですがエラーがでます どこが問題か教えていただけないでしょうか? #include <stdio.h> #define swap(type,a,b) (m = a a = b b = m) int main(void) { int x = 1,y = 2,m; swap(int,x,y); printf("x=%d y=%d\n",x,y); return(0); }

  • 【C++】関数からクラスに変更するには?

    いつも大変お世話になっています。 VC++初心者です。 関数をクラス化していきたいのですが、具体的にどのようにしたら良いか ご指導頂けませんでしょうか。 例えば、このようなソースがあった場合、どのようにクラス化させるのでしょうか。 (また、下記の例ですと、pulsとsubで1つのグループ、 goodMoringとgoodNightで1つのグループにさせる場合には どうすれば宜しいでしょうか。) //======================= //Tool.hの中身 //======================= int plus(int x, int y); int sub(int x, int y); void goodMorning(); void goodNight(); //======================= //Tool.cppの中身 //======================= #include <iostream.h> int plus(int x, int y){ return x + y; } int sub(int x, int y){ return x - y; } void goodMorning(){ cout << "おはよう\n"; } void goodNight(){ cout << "こんばんは\n"; } //======================= //Main.cppの中身 //======================= #include <iostream.h> #include "Tool.h" int main(){ int a = puls(1,1); cout << a <<'\n'; int b = puls(2,1); cout << b <<'\n'; goodMorning(); goodNight(); }

専門家に質問してみよう