🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

2回答

2094閲覧

関数内でメモリ確保後に、呼び出し元から確保したメモリが参照できません。

kamingout

総合スコア44

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/12/27 02:37

初歩的な質問で申し訳ないですが、わかる方教えてください。

関数A内でメモリを確保し、確保したメモリの情報を引数のポインタに返したいです。

関数A呼び出し元の関数B内では、ポインタunsigned char *pを定義します。
unsigned char *pを何か格納しておかないと関数Aを呼び出せないため、*p = NULLとします。

その後関数A内で newでpにメモリを確保したのちに処理を終了すると、関数B内で定義したpがNULLのままとなっております。
これは何が原因と考えられますか?

お手数おかけしますが、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2019/12/27 02:47

失敗したコードを書いていただけますか?(書かれた日本語と動作の違うコードを書いてしまっていることも考えられます)
maisumakun

2019/12/27 02:49

たとえば、「*p = NULLとします。 」が、「unsigned char * p = NULL;」と書いたのか、「unsigned char * p; *p = NULL;」なのか、文章だけでははっきりしません。
kamingout

2019/12/27 03:05

説明が不足しており申し訳ございません。 unsigned char * p = NULL; A(p); void A(unsigned char *p) unsigned char *test = new unsigned char[100]; p = test; になります。 何がいけないのでしょうか?
guest

回答2

0

こんにちは。

C++の引数の渡し方は分かりにくいのですが、「参照」を除いて値渡しと理解するのが良いです。
C言語は完全に全て値渡しです。C言語でも使える渡し方は値渡しと理解するのも手です。

さて、ポインタはC言語でも渡せますので、文法的には「値渡し」です。(意味的には「参照渡し」でもあるのでややこしいのですが。厳密な話しをするため今は狭い意味で文法にのみ着目下さい。)
ポインタの値は何かというと「アドレス」です。「質問への追記・修正」欄のソースの場合、test に設定されたアドレスが ポインタ変数testの値です。
関数A()が呼ばれた時、ポインタ型変数p(値はNULL)が値渡しされ、ポインタ型仮引数pへ値渡し(=コピー)されます。
仮引数pにはtestのアドレスが設定されますが、これは変数pがコピーされたものですのでtestのアドレスは変数pへは影響しません。つまり、返却されません。

例えば下記のように書くことができます。

C++

1void A(unsigned char **p) 2{ 3 // todo: pがNULLでないことをチェックする 4 5 unsigned char *test = new unsigned char[100]; 6 *p = test; 7} 8 9int main() 10{ 11 unsigned char * p = NULL; 12 A(&p); 13 delete[] p; 14}

もう一つC++らしい書き方としては以下のような方法もありますが、なかなか理解し辛いですので、微妙です。

C++

1void A(unsigned char*& p) 2{ 3 unsigned char *test = new unsigned char[100]; 4 p = test; 5} 6 7int main() 8{ 9 unsigned char * p = NULL; 10 A(p); 11 delete[] p; 12}

仮引数pは、unsigned char*への参照です。

投稿2019/12/27 04:33

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

何がいけないのでしょうか?

引数のpchar *型なので、pを変更しても呼び出し元へは変更した結果は戻りません。
引数char **pとして呼び出し元では、A(&p)としてアドレスを渡してください。

こういう事?

void foo(char* p){ char *mem; mem = (char *)malloc(sizeof(char)*100); p=mem; } void main (void){ char *str=null; foo(&str); if (str == null) { printf("str == null\n"); } else { printf("str != null\n"); } }

こうしないとだめだよ

void foo(char** p){ char *mem; mem = (char *)malloc(sizeof(char)*100); *p=mem; } void main (void){ char *str=null; foo(str); if (str == null) { printf("str == null\n"); } else { printf("str != null\n"); } }

投稿2019/12/27 03:00

編集2019/12/27 04:09
Y.H.

総合スコア7918

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問