質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.47%
ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

2回答

871閲覧

VC++ 配列のポインタについて

KKKM

総合スコア16

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/01/26 11:16

以下のようなプログラムを作りましたがうまくいきません。

関数bにて配列の一番最初の出力を行ってますが
printfの最初のみ正しく出力があり
それ以降は値がおかしくなります。

その原因として
ローカル変数であるA
が関数aの終了とともに消えてしまっているのではないかと考えています。
アドバイス頂けたらと思います。
よろしくお願いいたします。

long* a();
void b(long* hairetu);

int main(){

long* hairetu;

hairetu = a();

b(hairetu)

}

a(){

int A[100];
for (int i = 0; i < 100;i++ ){

A[i] = i;
}

return A;
}

b(long* hairetu){

printf("配列 %d\n",hairetu[0]);
printf("配列 %d\n",hairetu[0]);
printf("配列 %d\n",hairetu[0]);
}

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

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

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

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

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

guest

回答2

0

C

a(){
int A[100];
for (int i = 0; i < 100;i++ ){
A[i] = i;
}
return A;
}

これは期待通りには動作しないでしょう。主だった問題点は次の二つです。

  • 関数内で寿命を終える変数のアドレスを返していること
  • 返り値の型を省略していること (intがデフォルトの型として用いられています)

いくつか警告が出ている筈です。無視して実行してはいけません。


簡単には、次のように配列を呼び出し側で用意してやると良いでしょう。

C

1int main(void) { 2 long hairetu[100]; 3 a(hairetu, 100); 4 b(hairetu); 5} 6 7void a(long *hairetu, size_t size) { 8 ... 9}

コードの貼り方について

teratailには、コードを見やすく表示する機能があります。
質問編集画面を開き、コードを選択した状態で<code>ボタンを押して下さい。
C++

投稿2020/01/26 11:27

編集2020/01/26 11:30
LouiS0616

総合スコア35660

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

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

KKKM

2020/01/26 11:41

ご回答いただきまして ありがとうございます。 今回サンプルとして乗せた部分は 実際に使っていたソースの要約?に近い形になるように手打ちしたものです。 見直ししたつもりが細部の記入ミスがありました。 >>返り値の型を省略していること これは実際には生じていませんでした。 従って やはり原因は >>関数内で寿命を終える変数のアドレスを返していること にあるようです。 またこの問題の改善策として、 Aをstaticにしようか,グローバルにしようか悩んでいましたか main 関数内で定義する方法は思いつきませんでした。 大変貴重なご意見有難うございます。 mainで宣言するように変更しようと思います。 最後に主題とは異なりますが。 先ほどのAをstaticにした場合には データが保持されますが もしaの関数を何度も呼び出し、尚且つ代入する範囲を狭めたり 広めたりした場合には 前の値が残っている可能性がある(staticは初期化されないため)と思うので staticはやめたほうがいいと思うのですが認識はあっているでしょうか。
LouiS0616

2020/01/26 11:59 編集

まず表面的な指摘から。『staticは初期化されない』というのは誤りです。 寿命があるうちに領域内のデータが勝手に書き換わらないのはどんな変数でも同じです。static変数はプログラム全体と同じ寿命を持ちます。 一方、関数内で宣言した配列は初期化されていませんので、心配なようであれば long hairetu = {} などと明示的に書く必要があります。この場合全要素が0として初期化されます。 --- > もしaの関数を何度も呼び出し、尚且つ代入する範囲を狭めたり広めたりした場合 確かに同じ配列を何度も使いまわしたいのであれば、static変数は避けた方が良いでしょう。 呼び出し側で必要な長さの配列を用意するのが無難です。 あるいは、C++ならば可変長配列(vector)を簡単に利用できますので、それを使っても良いです。コーディングが楽になります。
guest

0

こんにちは。

C++には便利な機能があるので使いましょう。

C++

1#include <cstdio> 2#include <array> 3 4typedef std::array<int, 100> Hairetsu; 5 6Hairetsu a(); 7void b(Hairetsu const& hairetu); 8 9int main() 10{ 11 Hairetsu hairetu = a(); 12 b(hairetu); 13} 14 15Hairetsu a() 16{ 17 Hairetsu A; 18 for (int i=0; i < A.size(); ++i) 19 { 20 A[i] = A.size()-i; 21 } 22 23 return A; 24} 25 26void b(Hairetsu const& hairetu) 27{ 28 printf("配列 %d\n",hairetu[0]); 29 printf("配列 %d\n",hairetu[0]); 30 printf("配列 %d\n",hairetu[0]); 31}

まず、std::array<int, 100>はint型の要素を100個持つ固定長配列型の「クラス」です。
固定長の配列なら std::array を使うと幸せになれることが多いです。

次に return A; は、使い方に注意が必要ですが、これはNVROと呼ばれる最適化により、コピーされない処理系が多いです。(メジャーどころはたいていOKらしい。)
つまり、一見おもた~いコピーしてしまいそうですが、コロンブスの卵的な最適化により、この記述は意外に使えます。

投稿2020/01/26 13:09

Chironian

総合スコア23272

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問