「配列x1[ ]の各要素を順番に調べ、奇数のみをx2[ ]にコピーしたいとき、次のプログラムの空欄を埋めなさい」
という問題で、
int *p1,*p2;
p1 = x1;
p2 = x2;
while ( (1) > 0){
if( (1) %2 == 1){
(2);
(3)++;
}
(4) ++;
}
となっているのですが、
(3)(4)は参照するアドレスを1移動するという意味で
(3)*p2
(4)*p1
と考えていました。
ですが、正答は
(1)*p1
(2)*p2 = *p1
(3)p2
(4)p1
です。
(1)と(2)に関してはなぜ直接p1、p2の要素数を調べるのではなくポインタの変数を使うのか、
(3)と(4)に関してはなぜアドレスを1移動させてはいけないのか、
(文章が少しおかしいかもしれませんが...)よく理解できませんでした。
なぜこのような解答になるのか、教えていただきたいです。
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答6件
0
この問題が分からないということは、
ポインタのアドレスと指示先の変数の区別がつかないということです。
p1とp1の区別ができれば、もうほとんど解けている問題です。
p1とp1の具体的な値は何か、書き出すだけで理由も分かります。
C言語のポインタは体育の逆上がりのようなつまづきポイントなので、
小手先だけで答えを合わせるだけでなく、じっくり腰をすえて取り組んでください。
番地のたとえはもうご存じだとは思いますが、ただ知っているというだけでなく、
コードを見ても瞬時にイメージできるようになってください。
投稿2015/07/21 13:19
総合スコア5592
0
なんだか、何を基準に判断して良いのか。という部分から完全に混乱しているように見受けられます。
まず、変数を使うには宣言が必要です。
そして宣言によって用意された変数は、それぞれ記述によって振る舞いを変化させます。
ですので、それぞれの記述の見分けが必要になります。
C
1int value1 = 1; //変数(int):value1 に 1を代入 2int value2 = 2; //変数(int):value2 に 2を代入 3int* pValue1 = &value1; //変数(intのポインタ):pValue1に value1のアドレスを代入 4int* pValue2 = &value2; //変数(intのポインタ):pValue2に value2のアドレスを代入 5 6//この2つは同じ意味になる。 7value1 = value2; 8*pValue1 = *pValue2; 9 10//これはアドレスの代入 (この後に *pValue1と書くと value2の値を指すようになる) 11pValue1 = pValue2;
いろいろ書いてますが、上記が基本です。
指定した型の変数には、値やアドレスを1つ代入できます。
上記の場合に、「int変数の値」を表現するには2つの形式があります。
1つめは「value1, value2」で、これは "int変数の値" を意味します。
2つめは「*pValue1, *pValue2」で、こっちは "intのポインタ変数のアドレスの中身(=int変数の値)" です。
「int変数のアドレス」を表現するにも2つの形式があります。
1つめは「&value1, &value2」で、これは "int変数のアドレス" を意味します。
2つめは「pValue1, pValue2」で、こっちは "intのポインタ" です。
通常の変数とポインタ変数とで、修飾のされ方と修飾された場合の意味合いが異なる点に注意してください。
&修飾によるアドレス参照は、指定型の変数が格納されているアドレスを表します。
その意味で、基本的にポインタと等価のものです。
(※アドレス参照はポインタ変数ではなく、単に変数の中身を格納するアドレスを得られるだけです。ここにアドレスを渡しても変数ポインタのようには使えません。変数と値の区別も忘れないでください。)
ポインタ変数の方は、指定型の変数の格納されたアドレスそのものを格納する変数です。
つまり、変数のようになにかの値(データ)を格納しているけれども、実際に扱っている内容はデータではなくアドレスになります。
ポインタの理解をするには、これらの違いを区別できないと先に進めません。
まずは、この区別をつけられるようにしてください。
次に、配列の場合。
C
1int array[] = {0,1,2,3,4}; //変数(intの配列):array に 0〜4を設定 2int* pArray = array; //変数(intのポインタ):pArrayに arrayの先頭アドレスを代入 3 4//配列の変数とポインタは同じように振る舞う 5if(pArray[1] == array[1]) 6 printf("true¥n"); 7else 8 printf("false¥n");
配列の場合は、指定の型の変数の場合と少し趣が異なります。
添え字の括弧が付く・付かないの違いで、配列に格納された値を示したりポインタになったりします。
またポインタ変数の方は、配列の添え字なしのものと同じ振る舞いをします。
このあたりの区別がつけられるようになりましょう。
分かっていないと、ポインタの加減算は意味不明になると思います。
投稿2015/07/21 19:35
編集2015/07/21 22:10
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

退会済みユーザー
2015/07/24 13:02 編集

0
(3)と(4)に関してはなぜアドレスを1移動させてはいけないのか、
こちらについては、他の方が回答しているので省略します。
(1)と(2)に関してはなぜ直接p1、p2の要素数を調べるのではなくポインタの変数を使うのか、
こちらについては
int i,j;
i=j=0;
と言う宣言があれば、
(1)p1[i]
(2)p2[j]=p1[i]
(3)j++
(4)i++
のように配列の要素を操作しても同じような動きをします。
ポインタについての理解を問いたいからという出題の意図が主かもしれませんが、
動作速度向上のために行う理由もあります。
p1[i]と*(p1+i)、p2[j]と*(p2+j)が同じ動きなので、p1[i]やp2[j]といった書き方をすると
p1[i]やp2[j]で要素を参照するときと、i++やj++で添字を操作するときとでそれぞれ2回加算をすることになります。
それよりは、p1++やp2++として加算回数を減らして動作速度を(ちょっと)早くするといったことをします。
投稿2015/07/21 17:16
総合スコア985
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
(1)と(2)に関してはなぜ直接p1、p2の要素数を調べるのではなくポインタの変数を使うのか、
p1にはp1 = x1; この記述によってx1[0]のメモリ上の位置が代入されています。
p1これでx1[0]の値を参照します。
ループ1回目のp2 = *p1; は(x[0]が奇数ならですが)x2[0]=x1[0];と同じです。
(3)と(4)に関してはなぜアドレスを1移動させてはいけないのか、
アドレスを1つ移動させるという考え方で問題ないです。
正答の記述こそが正にそれを行っていたということですね。
ただ*p1++;でも結果としては同じだったような……
確かp1で指すデータを取り出し、その後p1を1つ進めるって処理になったはずです。
前半分の処理が全く無駄ですが、結果は同じになるのだったかと
(2)と(3)をまとめて *p2 = *p1++; みたいな記述がシンタックス的には有効(p2にp1を代入した後、p1をインクリメントするような振る舞いになるはず)だったと思いますが、ソースの可読性を落とすだけなので忘れてしまうのが懸命です。
※最後のはちょっと自信ないです。すみません。
ところで、質問には直接関係なくて申し訳ないです。
(1)が*p1とのことですが、という事は「while ( *p1 > 0)」?。
x1[]に0以下の値が存在するケースを想定しており、あったら(作業の途中なのに)そこでループ抜けちゃうんですかね?
試験でこの問題に当たったら(1)に何入れるか悩みそうです。
またc言語に触れなくなって久しいので記憶が曖昧ですが、この記述って配列末尾でエラー出ませんでしたっけ?
x1[]内の値は最後のみ0で他は0以上の整数です。って設定があったり
「while(*p1)」か「while(*p1 != NULL)」の書き間違いでしょうか?
投稿2015/07/21 16:44
総合スコア2068
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
なんだか自信がないですが間違ってたらごめんなさい。
int *p1;
というポインタの定義ですが、
この場合、p1は値のアドレス
*p1は値そのものをさします。
ですから、例えば
.......
int *p1,nx=5;
px=&nx;
printf("*px=%d\n",*px);
.......
という場合
*px=5
と出力されます。
キモは
px ならnxのアドレスを表わす
*pxならnxのアドレスの中身を表わす
ということかな…
でで、質問者様の問題を見てみればあとは自ずと...
頑張ってください!
あと間違ってたらご指摘お願いします。
投稿2015/07/21 13:46
総合スコア10
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/07/21 16:27

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。