C言語関係掲示板

過去ログ

No.1124 call by referenceについて

[戻る] [ホームページ]
No.2021

call by referenceについて
投稿者---新参者(2004/06/15 10:49:25)


Cをはじめて3ヶ月の超初心者です。

呼び出しもとの実引数を参照し、文字列検索関数によりマッチングしたデータを一覧表示し、呼び出し元に戻ったら全てのデータを表示させるプログラムを作成していますが、呼び出し元のデータも文字列検索関数と同じになってしまい困ってます。どなたかよい案をご教授ください。

例)元のデータ
1,山田太郎,岡山県,000
2,鈴木花子,沖縄県,000
3,佐藤一郎,東京都,000
4,加藤お茶,北海道,000

というデータで名前に"郎"を含んでいるデータを抽出する

結果)
1,山田太郎,岡山県,000
3,佐藤一郎,東京都,000
を表示させる。
/* 呼び出し先関数ででこの結果を出す

全て表示させる(呼び出し元関数に戻る)を選ぶと元のデータを、また見ることができる。

要約すると、call by reference で call by value みたいな独立性をもたせたいんです!

ちなみに、csv形式ファイルにデータを保存させています。
左からid番号,名前,住所,電話番号です。

説明べたで判りにくいかも知れませんがお力添えをよろしくお願いします。



No.2022

Re:call by referenceについて
投稿者---REE(2004/06/15 11:49:05)


>要約すると、call by reference で call by value みたいな独立性をもたせたいんです!

呼び出し先で、呼び出し元のデータを破壊しないようにして下さい。

破壊されたくない引数の型にconstを付加することをお勧めします。



No.2023

Re:call by referenceについて
投稿者---あかま(2004/06/15 12:00:45)


>呼び出し元のデータも文字列検索関数と同じになってしまい困ってます。
>要約すると、call by reference で call by value みたいな独立性をもたせたいんです!
call by referenceで渡された値を変更しなければいいだけでは?
明示的に示したいならconstを使って。

どうしても一時的に変更しなければいけないなら、別の変数に移し変えなければいけないと思いますが、
それだと結局はcall by valueと変わらないでしょう。

ちょっとやりたいことが分かりにくいので、
プログラムを載せていただければなにかアドバイスができるかもしれません。
まずデータを検索するのにデータを変更する必要はないですから。






No.2027

プログラムを載せました
投稿者---新参者(2004/06/15 13:13:04)


>ちょっとやりたいことが分かりにくいので、
>プログラムを載せていただければなにかアドバイスができるかもしれません。

操作ポイントとなるところを抜粋しました。
呼び出し元関数で一度一覧表示をさせ、そこから文字列検索関数に行きマッチしたデータチェーンでつなぎそれを表示させます。
そこから、また一覧表示を見ることも出来るということをやりたいのです。

typedef struct data {
  long id;
  char *name;
  char *sub_name;
  char *address;
  char *tel;
  struct data *before;
  struct data *next;
}Address;

/*呼び出し先関数*/
void name_search(Address *);

/*呼び出し元関数*/
void list();
Address *listwp = NULL;

/*liststartには構造体の先頭アドレスが格納されています*/
listwp = (*liststart);

/*全てのデータを表示させる*/
while(listwp != NULL){
 printf("%03ld\t名前:%s\tフリガナ:%s\t住所:%s\t電話番号:%s\n",listwp->id,listwp->name,listwp->sub_name,listwp-   >address,listwp->tel);
 listwp = listwp->next;
}

/*文字列検索関数へ*/
name_search(*liststart);

戻ってきたら、一覧表示させるかユーザに尋ねる。


/*-------------------------------------------------------*/
/*呼び出し先関数、文字列検索関数*/
void name_search(Address *restart){
  Address *wp; /*作業用ポインタ*/
  char *name; /*被検索文字列用ポインタ*/
  char *strp;
  char str[256]; /*検索文字用*/
  int i = 0;

    
  printf("検索する名前の一部,全てを入力してください\n");
    
  /*検索名前入力*/
  fgets(str,sizeof(str),stdin);
  str[strlen(str) - 1 ] = '\0';
  fflush(stdin);
  
  for(wp = restart; wp != NULL; wp = wp->next){
    strp = str;
    name = wp->name;
    while(*name !='\0' && *strp != '\0'){
      if(strncmp(strp,name,1) == 0){
        ++strp;
        ++name;
        if(*strp == '\0')
          マッチングしたデータをチェーンでつなげる
      }else{
        strp = str;
        ++name;
      } 
    }
  }
 ここでマッチングしたデータの表示をさせる
}









No.2028

Re:プログラムを載せました
投稿者---REE(2004/06/15 13:33:52)


>操作ポイントとなるところを抜粋しました。
>呼び出し元関数で一度一覧表示をさせ、そこから文字列検索関数に行きマッチしたデータチェーンでつなぎそれを表示させます。

ここで、つなぎ直してしまうことにより、元のデータが破壊されています。

文字列検索関数が表示するだけでよいのなら、つなぎ直す代わりに、そのまま表示すればよいです。



No.2029

Re:なるほど
投稿者---新参者(2004/06/15 13:46:07)


>ここで、つなぎ直してしまうことにより、元のデータが破壊されています。
>
>文字列検索関数が表示するだけでよいのなら、つなぎ直す代わりに、そのまま表示すればよいです。

なるほど!そうですね。言われてみれば確かにそうです。
ありがとうございます。
でも、私がやろうとしてることはできないんでしょうか?
表示させるほうが要領がが良いことはわかりましたが、せっかく考え込んだん方法なんで、後学のために出来る方法を学習したいです。
わがままばかりで申し訳ありませんが、ご教授宜しくお願いします。



No.2031

Re:なるほど
投稿者---REE(2004/06/15 15:03:55)


>表示させるほうが要領がが良いことはわかりましたが、せっかく考え込んだん方法なんで、後学のために出来る方法を学習したいです。
>わがままばかりで申し訳ありませんが、ご教授宜しくお願いします。

今の状態を出来るだけ残したいのなら、どこかでデータを複製すればよいです。

また、検索時に、元のデータを繋ぎ変える代わりにマッチしたデータだけを複製して、新たにリストを構築するという方法もあります。



No.2033

ありがとうございます
投稿者---新参者(2004/06/15 15:11:26)


>今の状態を出来るだけ残したいのなら、どこかでデータを複製すればよいです。
>
>また、検索時に、元のデータを繋ぎ変える代わりにマッチしたデータだけを複製して、新たにリストを構築するという方法もあります。

ご教授ありがとうございます。アドバイス通りに組みなおしてみます。
お手数掛けました。ありがとうございます。




No.2058

Re:call by referenceについて
投稿者---塗り壁(2004/06/16 12:56:59)


粗探しで悪いのですが、指摘させてもらいます。
Cには参照渡しは有りません。ご提示のものはあえて言えば、
アドレス渡しですが本質は値渡しです。


No.2070

Re:call by referenceについて
投稿者---REE(2004/06/17 13:47:31)


>粗探しで悪いのですが、指摘させてもらいます。
>Cには参照渡しは有りません。ご提示のものはあえて言えば、
>アドレス渡しですが本質は値渡しです。

確かに、C言語には参照型はありません。
しかし、一般的にC言語でも渡したい変数のポインタを関数に渡すことを、
参照渡しと表現します。
本質が値渡しだとしても、目的としての参照渡しという言葉を使うことに問題ありますか?



No.2075

Re:call by referenceについて
投稿者---NykR(2004/06/17 18:47:49)


>>Cには参照渡しは有りません。ご提示のものはあえて言えば、
>>アドレス渡しですが本質は値渡しです。
>本質が値渡しだとしても、目的としての参照渡しという言葉を使うことに問題ありますか?

問題あると思いますが。
Cで参照渡しのようなことをしたいときは、呼び出し側でオブジェクトへの参照を作り出してそれを値渡ししなければなりません。
ですから、プログラマは「本質は値渡し」であることを明確に意識する必要があります。
意識しなければならない点が見えにくくなるような言葉を使うことには問題があるのではないでしょうか。

# ちなみに私は“参照の値渡し”と呼んでいます。

# ついでにいえば、元々の質問は「call by reference」とは実は関係ありません。構造体を値渡ししても起こり得る問題です。


No.2076

Re:call by referenceについて
投稿者---円零(2004/06/17 18:54:21)


たとえば関数に*objectXを渡した場合、
「*objectXを値渡ししている」
「objectXを参照渡ししている」
ってことでいいじゃないですか。

単に「目的語がないと言葉の意味が取りにくいですね」
と言う話をしてるに過ぎないような気が。


No.2078

Re:call by referenceについて
投稿者---NykR(2004/06/17 21:41:34)


>たとえば関数に*objectXを渡した場合、
>「*objectXを値渡ししている」
>「objectXを参照渡ししている」
>ってことでいいじゃないですか。

「objectXを参照渡し」とは、呼び出し側が objectX を渡し、呼び出され側が objectX を左辺値として受け取ることを意味します。
従って、「関数に*objectX(&objectX ?)を渡した場合」は、objectXへの参照を渡していることにはなるかもしれませんが、「objectXを参照渡し」していることにはなりません。

Cではポインタを使えば参照渡しの利点を享受することはできますが、その内容に参照渡しと似たところは一つもありません。

>単に「目的語がないと言葉の意味が取りにくいですね」
>と言う話をしてるに過ぎないような気が。

少なくとも私はそのような話はしていません。


No.2081

Re:call by referenceについて
投稿者---円零(2004/06/17 22:53:24)


あ、そうか。アドレスの方は&objectXと書くべきでしたか。

しかし、「参照渡し」って用語ないし概念はCの規格で決まってるんですか?
そうでなかったら参照を渡すことを参照渡しと言ったって間違いとは言えないと思います。
渡した瞬間がobjectXでなくたって、参照できるように引数を渡してるんだから同じ事です。
「objectXの参照渡し」と言えば、&objectXを参照渡ししていると思う人はいませんよね?

Cで「文字列」と言う度に「char型の配列」と訂正されたらたまらないと思う。
このケースと全く等質とは言いませんが。


No.2083

Re:call by referenceについて
投稿者---YuO(2004/06/17 23:52:17)


>あ、そうか。アドレスの方は&objectXと書くべきでしたか。

アドレスとは何を指しているのですか?

式「&objectX」の値は「ポインタ」と呼びます。


>しかし、「参照渡し」って用語ないし概念はCの規格で決まってるんですか?

参照渡し,という用語も概念も規格には存在しません。
索引で引いた場合,referenceという単語が先頭に来るのはreferenced typeだけです。


>そうでなかったら参照を渡すことを参照渡しと言ったって間違いとは言えないと思います。

本当に参照を渡すのであれば参照渡しでよいでしょう。
C++やJavaなどではそれが可能です。

ポインタを渡すことによってそのポインタが参照するオブジェクトを間接的に渡すことを,
参照渡しと言うのは勝手ですが,その意志が伝わることは期待できませんが。

そのような怪しげな表現を使わなくても,「ポインタを渡す」と素直に言えばよいだけですし。


>Cで「文字列」と言う度に「char型の配列」と訂正されたらたまらないと思う。
>このケースと全く等質とは言いませんが。

「文字列」はちゃんと規格において定義されています。
#7. Libraryであるあたりが弱々ですが……。


先の「アドレス」もそうですが,
紛れのない別の表現があるのに,紛れのある怪しげな表現を使う必要はないと私は考えます。



No.2094

Re:call by referenceについて
投稿者---HA(2004/06/18 14:14:02)


>>Cで「文字列」と言う度に「char型の配列」と訂正されたらたまらないと思う。
>>このケースと全く等質とは言いませんが。
>
>「文字列」はちゃんと規格において定義されています。
>#7. Libraryであるあたりが弱々ですが……。
>

YuOさんが仰っているとおり、文字列の定義はあります。
char型配列と文字列は別のものです。

例えば、
char s[] = {'H','e','l','l','o'};
これは文字列ではありません。

釈迦に説法でしたか。すみませんでした。



No.2088

Re:call by referenceについて
投稿者---NykR(2004/06/18 09:45:23)


>しかし、「参照渡し」って用語ないし概念はCの規格で決まってるんですか?
>そうでなかったら参照を渡すことを参照渡しと言ったって間違いとは言えないと思います。

間違いだとは言ってませんが。
一般的には別の意味で用いられている用語に、勝手な定義を暗黙に与えることには *問題がある* と言っているだけで。


>渡した瞬間がobjectXでなくたって、参照できるように引数を渡してるんだから同じ事です。
>「objectXの参照渡し」と言えば、&objectXを参照渡ししていると思う人はいませんよね?

でも objectXを参照渡ししていると思う人はいるかもしれませんよね。
通常“参照渡し”とは、引数を左辺値として渡すことであって、引数を参照できる値を渡すことではありません。
呼び出すときだけでなく、関数定義を書くときにもこの違いは明確に意識する必要があります。


> Cで「文字列」と言う度に「char型の配列」と訂正されたらたまらないと思う。
> このケースと全く等質とは言いませんが。

「char型の配列」を「文字列」と呼ぶことにする。と最初に断っておけばいいのです。


No.2089

Re:call by referenceについて
投稿者---REE(2004/06/18 11:13:25)


>通常“参照渡し”とは、引数を左辺値として渡すことであって、引数を参照できる値を渡すことではありません。

下記サイトを見る限り、それが通常とは思えませんが、いかがでしょうか?
http://software.nikkeibp.co.jp/software/yougo/yougo3.html#yougo64
http://www.geocities.co.jp/SiliconValley/5634/t82B3_0008.html#2478

>呼び出すときだけでなく、関数定義を書くときにもこの違いは明確に意識する必要があります。

もちろん、文法的には値渡しであることは事実であり、
コーディングでは明確に意識する必要があります。



No.2091

Re:call by referenceについて
投稿者---NykR(2004/06/18 11:57:57)


>>通常“参照渡し”とは、引数を左辺値として渡すことであって、引数を参照できる値を渡すことではありません。
>
>下記サイトを見る限り、それが通常とは思えませんが、いかがでしょうか?
>http://software.nikkeibp.co.jp/software/yougo/yougo3.html#yougo64
>http://www.geocities.co.jp/SiliconValley/5634/t82B3_0008.html#2478

そうですね。言葉を間違えました。済みません。

| 引数を参照できる値を渡すことではありません。

オブジェクトを参照できる値を引数として渡すことではない。に訂正します。


>>呼び出すときだけでなく、関数定義を書くときにもこの違いは明確に意識する必要があります。
>
>もちろん、文法的には値渡しであることは事実であり、
>コーディングでは明確に意識する必要があります。

ですから、単に“参照渡し”と言ってしまうのは問題だと思ったわけです。
以下のように便宜的にそういっているにすぎないことがわかるような表現なら問題はないと思います。

参照渡し
参照渡しのようなもの
目的としての参照渡し(ってNo.2070はこう言いたかったわけではないですよね?)
etc.


No.2092

Re:call by referenceについて
投稿者---REE(2004/06/18 13:41:01)


>参照渡し
>参照渡しのようなもの
>目的としての参照渡し(ってNo.2070はこう言いたかったわけではないですよね?)
>etc.

No.2070では、明確に「目的としての参照渡しという言葉を使うことに問題ありますか?」と書いています。

ただし、少なくとも「参照渡しのようなもの」とは思っていません。
紛れも無く「参照渡し」です。



No.2105

Re:call by referenceについて
投稿者---塗り壁(2004/06/18 23:40:33)


議論の食い違いは、言葉の定義がすれ違っていることがほとんどですが、
今のスレッドもその例にもれないような気がする。
規格等で参照渡しがどう定義されているか誰か教えてくれませんか。
探し方が悪いのか私には見つからなかった。

取り敢えず私の認識では、参照渡しや値渡しは言語のメカニズム
のレベルのものと捉えています。前者は引数の同一実体の別名を
定義するメカニズム、後者は引数の複製を定義するメカニズム。

それに対し、アドレス云々等はあくまでアプリケーションレベルの話であって、このレベルの違いを無視した議論は納得できません。
従って、No.2089で紹介しているサイトについても内容的に疑問を持っています。

>ただし、少なくとも「参照渡しのようなもの」とは思っていません。
>紛れも無く「参照渡し」です。

その根拠は何ですか。


No.2113

Re:call by referenceについて
投稿者---とおり(2004/06/20 03:34:23)


要は、「reference」「参照」って単語を
・規格内の意味で使うか
・普通に日本語の意味として使うか
という違いだと思います。
# 上記単語は別にC言語用の単語でも何でもなく、一般用語ですから。
# *pointer というようにポインタの先を手繰るのを「dereference」と
# 言うのを聞いたことがありますし…

特にどちらの意味かを明示せずに使用した場合に、どっちの意味と取るのか
という点に関して、いろいろ意見があるということかと。


No.2114

Re:call by referenceについて
投稿者---REE(2004/06/21 10:47:57)


>議論の食い違いは、言葉の定義がすれ違っていることがほとんどですが、
>今のスレッドもその例にもれないような気がする。

この内容に同意します。
このままでは、進展は無いと思いますので、
この件に関しては最後の返信としたいと思います。

>それに対し、アドレス云々等はあくまでアプリケーションレベルの話であって、このレベルの違いを無視した議論は納得できません。
>従って、No.2089で紹介しているサイトについても内容的に疑問を持っています。

念のため、補足しておきますと、2089で紹介したサイトは、
一般的な認識ではないということを言いたかっただけで、その内容が絶対的に正しいとは思っておりません。



No.2118

Re:call by referenceについて
投稿者---NykR(2004/06/21 11:49:00)


>>議論の食い違いは、言葉の定義がすれ違っていることがほとんどですが、
>>今のスレッドもその例にもれないような気がする。
>この内容に同意します。
>このままでは、進展は無いと思いますので、
>この件に関しては最後の返信としたいと思います。

| >ただし、少なくとも「参照渡しのようなもの」とは思っていません。
| >紛れも無く「参照渡し」です。
|
| その根拠は何ですか。

これはどうなったのですか?


>>それに対し、アドレス云々等はあくまでアプリケーションレベルの話であって、このレベルの違いを無視した議論は納得できません。
>>従って、No.2089で紹介しているサイトについても内容的に疑問を持っています。
>
>念のため、補足しておきますと、2089で紹介したサイトは、
>一般的な認識ではないということを言いたかっただけで、その内容が絶対的に正しいとは思っておりません。

No.2088で書き間違えた私の認識

| 通常“参照渡し”とは、引数を左辺値として渡すことであって、
| 引数を参照できる値を渡すことではありません。

はNo.2089で紹介されたサイトを見る限り一般的な認識ではないということですね。

ですが、書き間違いを修正した私の認識(No.2091)

| 通常“参照渡し”とは、引数を左辺値として渡すことであって、
| オブジェクトを参照できる値を引数として渡すことではない。

とNo.2089で紹介されたサイトの説明は、同じことを言っています。つまり、どちらも、引数を渡す方式を表す用語だと。
ですから、言葉の定義のすれ違いはないと思います。


No.2124

Re:call by referenceについて
投稿者---REE(2004/06/21 13:49:38)


>| >ただし、少なくとも「参照渡しのようなもの」とは思っていません。
>| >紛れも無く「参照渡し」です。
>|
>| その根拠は何ですか。
>
>これはどうなったのですか?

私は、「参照渡しのようなもの」ではなく「参照渡し」と思っていたということです。
私は、「参照渡し」を、「関数呼び出し元の変数を関数側で変更できるように渡す方法」と認識していました。

>| 通常“参照渡し”とは、引数を左辺値として渡すことであって、
>| オブジェクトを参照できる値を引数として渡すことではない。
>
>とNo.2089で紹介されたサイトの説明は、同じことを言っています。つまり、どちらも、引数を渡す方式を表す用語だと。
>ですから、言葉の定義のすれ違いはないと思います。

これまでのやり取りを見直して、
自分が引数と変数を混同していたことに気がつきました。

そして、「参照渡し」は「引数を渡す方式」だから、「変数を渡す方式」として使うのは紛らわしい、ということで納得しました。