Outline ポインタの基本(復習) ミニテスト(問1)

http://apple.ee.uec.ac.jp/isyslab
http://apple.ee.uec.ac.jp/isyslab
Outline
‡ 先週の復習
基礎プログラミングおよび演習 第11回
‡ ポインタの基本
ポインタその2 on 2010.01.20
‡ 課題の復習
‡ 配列とポインタ
電気通信大学大学院電子工学専攻
電子知能システム学講座
長井隆行
‡ 本日の演習課題
2
http://apple.ee.uec.ac.jp/isyslab
http://apple.ee.uec.ac.jp/isyslab
ポインタの基本(復習)
‡
ミニテスト(問1)
変数に&演算子を適用すると、その変数のアド
レス(メモリの番地)が取得できる
#include<stdio.h>
int main(void)
{
int x = 2;
int y = 4;
int* p_x;
⇒このアドレスのことを、その変数へのポインタと呼ぶ
ポインタ変数hoge_pが別の変数hogeのポインタ
を保持しているとき、hoge_pがhogeを指している
という
‡ ポインタに*演算子を適用すると、そのポインタ
の指している先を表すようになる
‡
p_x = &y;
*p_x = *p_x + x +y;
p_x = &x;
*p_x = *p_x + x + y;
/*変数の宣言*/
/*変数の宣言*/
/*ポインタ変数の宣言*/
/*アドレスをポインタ変数に代入*/
printf("results are %d and %d¥n", x, y);
return 0;
}
⇒ hoge_pがhogeを指しているなら、*hoge_pとhogeは同
じものを表す
p11-1.c
結果がどうなるか頭で考える!
3
4
http://apple.ee.uec.ac.jp/isyslab
http://apple.ee.uec.ac.jp/isyslab
前回の課題の復習
‡
アドレス渡し補足
ポインタと関数における引数の両方を理解していないとい
けない
#include<stdio.h>
アドレス渡しで、実引数はアドレス(&x)で仮
引数は値(*x)なのがなぜか?
‡ 単純にアドレスを代入する場面を考えてみる
‡
void swap(int* x, int* y)
{
int tmp;
void swap(int* x, int* y);
int main(void)
{
int x, y;
int x;
int* px;
x=10;
px = &x;
tmp = *x;
*x = *y;
*y = tmp;
x = 5;
y = 10;
}
swap( &x, &y );
なぜここがこうなるのか?
箱x(型はint)
main
func(&x)
p11-2.c
}
5
http://apple.ee.uec.ac.jp/isyslab
}
add
10
funcのローカル変数
func( int* x )
{
}
箱x(型はint*)
add
コピーされる
6
http://apple.ee.uec.ac.jp/isyslab
箱を考える
x = 5;
y = 10;
箱を用意して積め!
mainのローカル変数
関数になっていても同じ
{
printf(“x=%d, y=%d¥n”, x, y);
return 0;
int x,y;
これは、int* に & intがコピーされる形になっている
オ
tmp 空
エ
y イ
エ
y イ
ウ
x ア
ウ
x ア
‡ メイン関数で2つの変数x,yを用意する
‡ それらに適当な値を代入する(x,yの型に
イ
y空
イ
y 10
イ
y 10
イ
y 10
ア
x空
ア
x5
ア
x5
ア
x5
*y = tmp;
*x = *y;
tmp = *x;
ミニテスト(問2)
int tmp;
swap(&x, &y);
オ
tmp 5
オ
tmp 5
オ
tmp 5
エ
yイ
エ
y イ
エ
y イ
ウ
xア
ウ
x ア
ウ
x ア
イ
y 10
イ
y 10
イ
y5
ア
x5
ア
x 10
ア
x 10
ここの値を入れ替えたい!
7
注意)
‡ 値を2つ受取ってそれらの和と積を計算す
る関数を作る
‡ 結果をメインで受け取るにはどうすればよ
いか?
8
http://apple.ee.uec.ac.jp/isyslab
http://apple.ee.uec.ac.jp/isyslab
ミニテスト(問2) 続き
ミニテスト(問2) 解答例
void waseki(
{
#include<stdio.h>
void waseki(
#include<stdio.h>
)
void waseki(double x, double y,
double* p_wa, double* p_seki);
);
int main(void)
{
double x, y;
double wa, seki;
/*値は何でもよい*/
/*値は何でもよい*/
waseki(
*p_wa = x + y;
*p_seki = x*y;
int main(void)
{
double x, y;
double wa, seki;
}
x = 2;
y = 3;
x = 2;
y = 3;
p11-3.c
);
void waseki(double x, double y,
double* p_wa, double* p_seki)
{
}
答えをしまって欲しい
箱の場所を関数に渡している
waseki( x, y, &wa, &seki );
printf(“wa=%f, seki=%f¥n”, wa, seki);
return 0;
printf(“wa=%f, seki=%f¥n”, wa, seki);
return 0;
}
9
http://apple.ee.uec.ac.jp/isyslab
}
10
http://apple.ee.uec.ac.jp/isyslab
配列とポインタ
つまり・・・
hoge[0]のアドレスは&hoge[0]
‡ 山田さんの隣の家とか隣の隣ということが
よって、&hoge[0] ⇒ 0x10000000
できる!
‡ 配列の小箱はアドレスの順番に並んでい
ることがポイント
ここで、&hoge[0]を
hogeと書くことができる
*hoge は hoge[0]
*(hoge+1) は hoge[1]
*(hoge+2) は hoge[2]
を意味する
注)hogeはint型で4バイトなので、*(hoge+1)の+1はアドレスを4バイト
先に進めることを意味します
11
12
http://apple.ee.uec.ac.jp/isyslab
http://apple.ee.uec.ac.jp/isyslab
ポインタの演算
ちょっと余談ではありますが・・・
ポインタ(アドレス)を足したり引いたり(演算) して、
配列の位置を指定することができる。
ポインタの演算
‡ 配列の添え字はポインタ演算で置き換えられる
‡
hoge[5]
*(hoge+5)
昔は、ポインタ演算で書いた方が早かった
‡ C言語っぽい感じがする(玄人っぽい)
‡ 読みにくくなる場合は使うべきではない
‡
‡
p[i]とi[p]は全く同じ!?
#include<stdio.h>
int main(void)
証明
{
p[i]と*(p+i)は同じですね(配列とポインタ演算の関係)。
int i=0;
tnagai@golf-1[20]_% gcc -o irekae irekae.c
int p[10]={1,2,3,4,5,6,7,8,9,10};
ということは、加算は入れ替え可能ですから
tnagai@golf-1[21]_% ./irekae
*(p+i)
=
*(i+p)
p[0] = 1, 0[p]=1
for(i=0; i<10; i++)
p[1] = 2, 1[p]=2
{ ということになります。
p[2] = 3, 2[p]=3
printf("p[%d] = %d, %d[p]=%d¥n",i,p[i],i,i[p]);
これをまた配列とポインタ演算の関係で戻すと
p[3] = 4, 3[p]=4
}
p[4] = 5, 4[p]=5
return
0;
*(i+p)とi[p]は同じになります
p[5] = 6, 5[p]=6
}
で結局p[i]=i[p]とあいなります。
p[6] = 7, 6[p]=7
p[7] = 8, 7[p]=8
あら不思議・・・
p[8] = 9, 8[p]=9
p[9] = 10, 9[p]=10
tnagai@golf-1[22]_%
13
http://apple.ee.uec.ac.jp/isyslab
14
http://apple.ee.uec.ac.jp/isyslab
ミニテスト(問3)
ミニテスト(問3) 続き
void waseki(
{
‡ メイン関数で配列xを用意する
#include<stdio.h>
‡ それらに適当な値を代入する(xの型とサイ
void waseki(
ズに注意)
‡ 配列の全ての値を受取ってそれらの和と
積を計算する関数を作る
‡ 結果をメインで受け取るにはどうすればよ
いか?
int main(void)
{
double x[5]={1,5,3,6,2};
/*値は何でもよい*/
double wa, seki;
waseki(
)
);
);
}
p11-4.c
printf(“wa=%f, seki=%f¥n”, wa, seki);
return 0;
}
15
16
http://apple.ee.uec.ac.jp/isyslab
http://apple.ee.uec.ac.jp/isyslab
本日の演習
ミニテスト(問3) 解答例
#include<stdio.h>
void waseki(double* p_x,
double* p_wa, double* p_seki);
int main(void)
{
double x[5]={1,5,3,6,2};
/*値は何でもよい*/
double wa, seki;
void waseki(double* p_x,
double* p_wa, double* p_seki)
{
int i = 0;
*p_wa = 0;
*p_seki = 1;
‡
‡
‡
‡
‡
‡
}
printf(“wa=%f, seki=%f¥n”, wa, seki);
return 0;
}
‡
*p_wa = *p_wa + *(p_x+i);
*p_seki = *p_seki * *(p_x+i);
でもよい
17
http://apple.ee.uec.ac.jp/isyslab
修正前のソースコード(p11-5.c)
#include<stdio.h>
int main(void)
{
int i;
/*データ*/
double kion[31] = {32.3, 32.0,
32.6, 31.1,
34.9, 36.5,
23.4, 20.9,
double sum, heikin;
sum = 0.0;
for(i=0; i<31; i++)
{
sum = sum + kion[i];
}
heikin = sum/31.0;
printf(“heikin : %f¥n”, heikin);
return 0;
}
ー課題ー (ここから先をメールで送る)
‡ p11-5.cの平均値計算の部分を関数にする
‡
for(i=0; i<5; i++)
{
*p_wa = *p_wa + p_x[i];
*p_seki = *p_seki * p_x[i];
}
waseki( x, &wa, &seki );
ー準備ー
‡ まずは、p11-5.cをHPよりダウンロードする
‡ コンパイル、実行して正しく動作することを確認する
32.3, 33.6, 31.3, 33.2, 32.1, 31.9, 33.0,
32.6, 33.5, 34.7, 28.5, 30.3, 31.0, 35.1,
29.8, 29.8, 23.8, 31.7, 27.9, 29.2, 28.3,
29.7, 34.4};
/*sum += kion[i];でもよい*/
19
気温のデータをポインタを使って関数に渡す必要がある
平均値を計算してメイン関数に戻す(アドレス渡しでもよい)
ソースコードと実行結果をメールで送る
送る際には注意事項をよく確認すること
今日の講義の感想・質問をメール本文に書いてください
よく分かった、ここが分からない、など
コメントは楽しいのがgood
今日の課題は今日締め切り
18