参照渡しのしくじりとは?なぜ参照渡しができないのかを解説

このQ&Aのポイント
  • C言語での参照渡しに関する質問について、なぜ参照渡しができないのかを説明します。
  • 質問者は、メイン関数とtest関数でchar型のポインタを使って文字列を渡そうとしています。
  • しかし、値がうまく渡されない理由や参照渡しができない理由について詳しく解説します。
回答を見る
  • ベストアンサー

参照渡しにならないのは何故?

参照渡しにならないのは何故? 基本的な質問で大変恐縮なのですが、C言語で以下のコードを書いてみました。 メインの関数ではchar型のポインタのみ用意し、呼び出し先のtest関数内で当該ポインタ用に 領域を割り当て文字列をコピーしています。 ここまでは良いのですが、呼び出し元のメイン関数に戻るとtest関数にて設定したはずの値 が消えてしまいます。 結局のところ、メインの関数で用意したchar型のポインタがうまくtest関数にわたっていない (?)ような動作なのですが、どうしてこうなってしまうのか理解できず苦しんでいます。 ご教授いただければ幸いです。 #include <stdio.h> #include <stdlib.h> #include <string.h> void test(char *pc_buf){ pc_buf = (char *)malloc(10); memset(pc_buf,(int)NULL,10); strcpy(pc_buf,"12345"); return; } void main(){ char *pc_buf; pc_buf = NULL; test(pc_buf); printf("[%s]\n",pc_buf);getchar(); }

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

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

C言語では関数の引数は変数渡しであり、参照渡しにはなりません。 > void test(char *pc_buf){ ここで渡されたpc_bufはあくまで変数値としてchar型のポインタ変数が渡されているので、これ自体は関数test()のローカル変数にほかなりません。したがって > pc_buf = (char *)malloc(10); のようにしてもローカル変数のpc_bufにメモリのアドレスが設定されてるだけなので、呼び元のmain関数には渡されません。 これを回避するにはtest関数のパラメータとして、char型のアドレス変数のポインタを渡す必要があります。 void test(char **pc_buf){ *pc_buf = (char *)malloc(10); memset(*pc_buf,(int)NULL,10); strcpy(*pc_buf,"12345"); return; } void main(){ char *pc_buf; pc_buf = NULL; test(&pc_buf); printf("[%s]\n",pc_buf);getchar(); }

misshiki
質問者

お礼

ご回答ありがとうございました。 ご指摘の方法で動作することが確認できました。 まだまだ理解が及ばないポインタですが、今後も精進していきたいと思います。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「変数渡し」ではなく「値渡し」とすべきでしょう>#1. 場面にもよるけど「変数渡し」は「参照渡し」と同義であることもしばしばです. 念のためですが, C においては「値渡し」しかありません.

関連するQ&A

  • 一番大きい奇数を表示する

    scanf関数を使用して、文字列を10回入力し一番大きい文字列を表示するプログラムを作ったのですが、 一番大きい「奇数」を表示するように条件を加えた場合どうすればよいのでしょうか? 偶数=割り切れる 奇数=割り切れない ということまでは分かるのですがその先が分かりません。 一応一番大きい文字列を表示するプログラムを貼っておきます。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } if (strcmp(buf, str) > 0) { strcpy(str, buf); } printf("output>\n%s\n" , str); getchar(); }

  • 一番大きい奇数を表示する

    scanf関数を使って数字を10回入力して一番大きなものを表示させるプログラムをつくったのですが、 さらに一番大きな奇数を表示するにはどうすればいいのでしょうか? 偶数=割り切れる 奇数=割り切れない というところまでは分かるのですが、以下のプログラムに奇数を判別するソースを追加するのにはどうすればいいのでしょうか。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; int w; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } for (i = 0; i < 10; i++) { if ((buf[i] & 1) == 1) /* 奇数であるか */ { if (strcmp(buf, str) > 0) { strcpy(str, buf); } } } printf("output>\n%s\n" , str); getchar(); }

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

    参照渡し と ポインタ渡し はどういう時に使い分けるんですか? 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; } だとコンパイルエラーでした。 うまくいくソースを教えてください。

  • 関数のコピー

    以下のようなソースがあります。 していることは、char配列に関数をコピーしています。それを関数ポインタに変換して、実行しています。 自作の場合はできるのですが、 MessageBoxをコピーすると以下(字数の関係上無理でした。)のようにメモリ内容がなっており、そのままコピーしたつもりですが、若干異なっております。 どのようにすればMessageBoxがじっこうできるのか, 教えていただきたく質問しました。 よろしくお願いします。 mb,code3が該当分です。 //ソース #include<stdio.h> #include<memory.h> #include<windows.h> int func(int cnt) { return cnt*10; } int func2(int cnt,int cnt2) { return cnt+cnt2; } char *func3() { return "Hello"; } int main() { int (*fa)(int); //MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaotion,UINT uType); int (*fm)(int,int); int (*mb)(HWND,LPCTSTR,LPCTSTR,UINT); char *(*hl)(void); /*fa=func; printf("%d",fa(5)); getchar(); */ char code[12800]; char code2[12800]; char code3[80000]; char code4[12800]; memset(code,0,12800); memset(code2,0,12800); memset(code3,0,80000); memset(code4,0,12800); memcpy(code,(char *)func,12800); memcpy(code2,(char *)func2,12800); memcpy(code3,(char *)MessageBox,80000); memcpy(code4,(char *)func3,12800); fa=(int(*)(int))(void *)code; fm=(int(*)(int,int))(void *)code2; mb=(int(*)(HWND,LPCTSTR,LPCTSTR,UINT))(void *)code3; hl=(char *(*)(void))(void *)code4; printf("%d\n",fa(3)); printf("%d\n",fm(3000,10)); printf(hl()); MessageBox(NULL,"","",MB_OK); mb(NULL,"","",MB_OK); getchar(); return 0; }

  • new、memset()、エラー

    new は何型を返すんですか? new の定義が詳しく書いてあるサイトを紹介してください。 new して確保した領域のメモリは全て0で初期化されますか? それが分からなかったからmemset()で0にしてみたら、 memset()の部分で実行エラーでした。 new の領域をmemset()してはいけないんですか? #include <iostream.h> main(){ char *buf = new char[100]; memset(buf, 0, 100); delete []buf; }

  • CHAR型ポインタについて。

    CHAR型ポインタについて。 当方C言語初心者です。 ポインタと文字列の関係分からないことが出てきました。 参考にしている本があり、そのページに下記のソースで「const char *pc1」のポインタ変数を用意して、そこに直接文字列を代入しています。 本来、「char *pc1」はchar型のアドレスを格納するための変数のはずなのに、その変数に文字列を代入してることに疑問を感じました。 この記述の仕方は間違っていないのでしょうか?また、アドレスを格納するための変数「*pc1」に「abcdefg」の文字列はどのようにメモリ上で格納されているのでしょうか? 知ってどうなるの?みたいな質問かもしれませんが、ご教授いただけると幸いです。 #include <stdlib.h> #include <string.h> void func(void) { const char *pc1 = "abcdefg"; //←ココ char *pc2 = (char *)malloc( strlen(pc1) +1); if ( pc2 ) { strcpy( pc2, pc1 ); free( pc2 ); } }

  • ファイルから文字を読み込んで文字列を変換する

    ファイルから文字を読み込んで文字列を変換したいのですが 読み込み元が改行されていた場合がうまく変換できません。 読み込み元が改行されている事を教えればうまく行くと思うのですがどのようにすれば出来ますか? 出来ればソースの書き込みお願いします。 ---以下ソース--- #include <stdio.h> #include <stdlib.h> #include <string.h> int hen(char *buf, char *mae, char *ato); void main(void){ FILE *fp; char *f1="赤<br>と<br>白<br>"; char *h1="黄と黒"; char buf[200]; char set[200]; fp = fopen("ren2.html", "r+"); while( fgets( set, 200, fp ) != NULL ){ strcpy(buf,set); while(hen(buf, f1, h1)); printf("%s", buf); } fclose(fp); } int hen(char *buf, char *mae, char *ato){ char *nw; size_t zen,go; zen = strlen(mae); go = strlen(ato); if(zen == 0 || (nw = strstr(buf, mae)) == NULL){ return 0; } memmove(nw + go, nw + zen, strlen(buf) - (nw + zen - buf ) + 1); memcpy(nw, ato, go); return 1; } ---ソースここまで--- ---ren2.htmlの内容--- <html> <head> <title>練習</title> </head> <body> 赤<br> と<br> 白<br> </body> </html> ---ren2.htmlここまで---

  • NULL領域を読み書きするの意味が?

    C言語の初学者です。 コンパイラは、Borland C++ 5.5.1 for Win32 を使っています。 たまたま見つけた C magazine プログラミングの禁じ手Web版 C言語編で、「NULL領域を読み書きする」という個所があり、下記ソースで発覚すると掲載されていました。 (http://www.cmagazine.jp/src/kinjite/c/null.html#index5) void f() { static char *theTxt; strcpy(theTxt,"TEST\n"); printf("%s",theTxt); } 自分の環境で、下記のソースで動かしてみたところ、アプリケーションエラーになりました。 #include <stdio.h> #include <string.h> int main(void) { static char *theTxt; /* (1) */ strcpy(theTxt,"TEST\n"); printf("%s",theTxt); return 0; } この禁じ手の意味そのものが、全く理解できませんでした。 ・NULL領域というのは、(1)のstatic定義されたポインタことをさしているのか? ・(1)の static をつけないで実行すると、正常終了したので、static の領域に書き込んではいけないのか? (そんなことはないと思うのだが)

  • プログラミング(関数reverseを作る)

    プログラミングの勉強会で文字列を反転させる関数(例:ABCDE→EDCBA)を作れという課題が出たのですが、以下のように書いたきり進みません。あと、何を書けばいいのでしょうか?教えてください。 #include <stdio.h> void reverse(char *); void reverse2(char *); void main(){ char buf[10]; printf("str :"); fgets(buf, 10, stdin); reverse(buf); printf("rev :%s", buf); return; } //文字列を反転させる関数 void reverse(char *s){ return; }

  • C言語の変数について

    C言語の変数について教えていただきたいです。 C言語で下記のような設定をした場合、変数A、Bに設定する値にはバイト数制限 はないのでしょうか? バイト数制限がなくなる場合、なぜそうなるのかを教えていただきたいです。 よろしくお願いします。 #include <stdio.h> void test( char **B); int main( int argc, char *argv[] ) { char *A = NULL; char *B = NULL; A = argv[1]; test( B ); return 0; } void test( char **B ) { strcpy(B, "ABCD"); return 0; }

専門家に質問してみよう