# iostreamの<<の多重定義などのことは一切無視して,多少強引なやり方で話を進めます。
コード:
#include <iostream>
void test (int arg)
{
int n = 10;
arg = n;
}
int main (void)
{
int n = 20;
test(n);
std::cout << n << std::endl;
return 0;
}
が標準出力に20を出力することは理解できているでしょうか。
形式的に,intをchar *に置き換えると,
コード:
#include <iostream>
void test (char * arg)
{
char * n = 10;
arg = n;
}
int main (void)
{
char * n = 20;
test(n);
std::cout << n << std::endl;
return 0;
}
となります。もちろん,10や20がエラーになりますが,その点だけを修正すると,
コード:
#include <iostream>
void test (char * arg)
{
char * n = "test";
arg = n;
}
int main (void)
{
char * n = "main";
test(n);
std::cout << n << std::endl;
return 0;
}
となります。これは標準出力にmainという文字列を出力します。
さて,3番目のプログラムは,私が最初に提示したプログラムとは,intを単純にchar *に置き換え,エラーを潰すために整数定数を文字列に置き換えただけのものです。
つまり,最初のプログラムと3番目のプログラムに構造の違いはありません。
よって,main関数中のnはtestの呼び出しで変更されません。
そして,3番目のプログラムはテニスさんが書かれたプログラムと実質的に同じものです。
最初のプログラムでは,test関数に「nという変数」ではなく「nという変数の値」を渡しました。
構造が同じ3番目のプログラムでも,同じくtest関数に「nという変数」ではなく「nという変数の値」を渡します。
int型では「nという変数の値」はint型の値,つまりは整数値でした。
char *型では「nという変数の値」はchar *型の値,つまりはchar型のオブジェクトへのポインタになります。
swap関数という話が出て来たので,swap関数も例にしてみましょうか。
まずはintで。
コード:
#include <iostream>
void swap (int * lhs, int * rhs)
{
int temp = *lhs;
*lhs = *rhs;
*rhs = temp;
}
int main (void)
{
int n1 = 10;
int n2 = 20;
std::cout << "n1 : " << n1 << " / n2 : " << n2 << std::endl;
swap(&n1, &n2);
std::cout << "n1 : " << n1 << " / n2 : " << n2 << std::endl;
return 0;
}
次に,これを単純にintとchar *を置き換え。
コード:
#include <iostream>
void swap (char * * lhs, char * * rhs)
{
char * temp = *lhs;
*lhs = *rhs;
*rhs = temp;
}
int main (void)
{
char * n1 = 10;
char * n2 = 20;
std::cout << "n1 : " << n1 << " / n2 : " << n2 << std::endl;
swap(&n1, &n2);
std::cout << "n1 : " << n1 << " / n2 : " << n2 << std::endl;
return 0;
}
そして,char *になったことに伴うエラーつぶし。
コード:
#include <iostream>
void swap (char * * lhs, char * * rhs)
{
char * temp = *lhs;
*lhs = *rhs;
*rhs = temp;
}
int main (void)
{
char * n1 = "abc";
char * n2 = "zyx";
std::cout << "n1 : " << n1 << " / n2 : " << n2 << std::endl;
swap(&n1, &n2);
std::cout << "n1 : " << n1 << " / n2 : " << n2 << std::endl;
return 0;
}
このように,ある型Tの変数の中身を呼び出す関数側で書き換えたいならば,T *と宣言します。
# C++ならばT &でもよい。
「何の型を扱っているのか」を意識してプログラムを書くと,このあたりで悩むことはなくなると思います。