• 検索結果がありません。

ポインタと配列

N/A
N/A
Protected

Academic year: 2021

シェア "ポインタと配列"

Copied!
14
0
0

読み込み中.... (全文を見る)

全文

(1)

ポインタと配列

理工学部 情報科学科

上級プログラミング

(2)

ポインタの復習

ポインタはアドレスを代入するための変数

int a=10,b=20;

int *p, *q;

p=&a;

q=&b;

int sum=*p+*q;

a b

p q

アドレス 1200 1204 1208 1212 1216

・・・

・・・

・・・

1320 1324 1328

sum

ポインタを使用したコード例

メモリ内の様子

20 30

1204 1208

10

ポインタはアド レスを代入して

初めて使える

(3)

ポインタの復習

ポインタは「指し示すもの」なので以下のように表す。

コードを記述しているときは、アドレスの値は気にしないので・・・

int a=10,b=20;

int *p, *q;

p=&a;

q=&b;

int sum=*p+*q;

a b

アドレス 1200 1204 1208 1212 1216

・・・

・・・

・・・

1320 1324 1328

sum

ポインタを使用したコード例

メモリ内の様子

20 30

10

p

q

(4)

配列とアドレス

配列データは、同じ型のデータをメモリ内に連続して並べられる。

int a[10];

・・・

・・・

・・・

メモリ内の様子

アドレス 2500 2504 2508 2512 2516

2528 2532 2536

a[0]

a[1]

a[2]

a[3]

a[4]

a[7]

a[8]

a[9]

a

配列名は、その領域の 先頭アドレスを指す アドレス定数である

ポインタと似ているが、配列名 自体は変数ではないので、ポ インタのように他のアドレスを 代入し直すことはできない。

a

上記配列aの先頭アドレスは、

a

&a[0]

のどちらでも表せる。

(5)

配列とポインタ(1)

ポインタを用いて配列データの各要素にアクセスする方法

int a[10];

int *p;

・・・

・・・

・・・

メモリ内の様子

a[0]

a[1]

a[2]

a[3]

a[4]

a[7]

a[8]

a[9]

a

for(int i=0; i<10; i++) cin >> a[i];

for(p=a; p<a+10; p++) cin >> *p;

同じ処理を意味する

a+10

p

++で

p

1つ分 進む

--で1つ分 戻る

ポインタにとって++や--は指す位置を、

データ型1つ分ずらすことを意味する。

アドレスの値を1増減する意味ではない。

(6)

配列とポインタ(2)

ポインタを用いて配列データの各要素にアクセスする方法

int a[10];

int *p=a;

// pを配列aの先頭アドレスで // 初期化

・・・

・・・

・・・

メモリ内の様子

a[0]

a[1]

a[2]

a[3]

a[4]

a[7]

a[8]

a[9]

a p

*p または p[0]

*(p+1)またはp[1]

*(p+2)またはp[2]

*(p+3)またはp[3]

*(p+4)またはp[4]

*(p+7)またはp[7]

*(p+8)またはp[8]

*(p+9)またはp[9]

a[2]=38;

*(p+2)=38;

p[2]=38;

どれも同じ 代入

(7)

配列とポインタ(3)

ポインタを用いて配列データの各要素にアクセスする方法

int a[10];

int *p=&a[3];

// pをa[3]のアドレスで // 初期化

・・・

・・・

・・・

メモリ内の様子

a[0]

a[1]

a[2]

a[3]

a[4]

a[7]

a[8]

a[9]

a

p

*(p-3)

*(p-2)

*(p-1)

*pまたはp[0]

*(p+1)またはp[1]

*(p+4)またはp[4]

*(p+5)またはp[5]

*(p+6)またはp[6]

a[2]=38;

*(p-1)=38;

どちらも 同じ代入

(8)

ポインタ間の演算

◎同じ型の2つのポインタの差は定義されている int a[8];

int *p1=a, *p2=&a[5];

このあと、例えば p2-p1 という計算は可能

◎ポインタ間の差は整数となる

ポインタの指すオブジェクト単位で差を表す

何要素分ずれているかを示す

結果が負になることもある

同一配列内の要素へのポインタの差のみ計算は有効 上記の例で、

p2-p1

の値は

5

となる

◎2つのポインタの和は計算できない

cout << (p1 + p2); ←コンパイルエラー

(9)

二次元配列のアドレス

int a[5][7];

a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] a[0][5] a[0][6]

a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] a[1][5] a[1][6]

a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] a[2][5] a[2][6]

a[3][0] a[3][1] a[3][2] a[3][3] a[3][4] a[3][5] a[3][6]

a[4][0] a[4][1] a[4][2] a[4][3] a[4][4] a[4][5] a[4][6]

a[0]

a[1]

a[2]

a[3]

a[4]

二次元配列の

1

つ目の次元は、各行の先頭アドレスとなっている

a 二次元配列の名前は、その領域の先頭アドレスである

aa[0]&a[0][0] はどれも同じアドレスを持つ。

ただし、型が異なる。

a int [][]またはint**a[0]&a[0][0]int[]またはint*

(10)

コマンドラインの取得

コマンドラインへの入力例

comsv% example inputfile.txt 12 abc

この部分を受け取るのが

main

関数の引数

コマンド プロンプト

と呼ぶ

int main(int argc, char *argv[]){

どのようにコマンドラインを受け取っているのか?

(11)

コマンドラインの取得

コマンドラインへの入力例

comsv% example inputfile.txt 12 abc argc=4 「4つの文字列がある」

e x amp l e ¥0

i n p u t f i ¥0

1 2 ¥0 a b c ¥0

l e . t x t

argv[0]

argv[1]

argv[2]

argv[3]

要素数argcのポインタ配列

各ポインタが、各文字列の先頭アドレスを指している。

文字列リテラルは必ず

¥0(NULL文字、アスキーコー ドが0の文字)で終わる。

(12)

関数への配列渡し(例1)

int main(){

int ar[5]={4,6,2,3,1};

int sum;

sum=makeSum(ar,5);

・・・

int makeSum(int *ap, int n){

int s=0;

for(int i=0; i<n; i++) s+=ap[i];

return s;

}

4 6 2 3 1

ar

sum

main関数 makeSum関数

ap n s

0

5 4 10 12 15

16 16

i

012345

(13)

関数への配列渡し(例2)

int main(){

int ar[5]={4,6,2,3,1};

int sum;

makeSum(ar,5,&sum);

・・・

void makeSum(int *ap, int n, int *sp){

*sp=0;

for(int i=0; i<n; i++) *sp+=ap[i];

}

4 6 2 3 1

ar

sum

main関数 makeSum関数

ap n sp

5 0

i

012345

4 10 12 15 16

(14)

関数への配列渡し(例3)

int main(){

int ar[5]={4,6,2,3,1};

int sum;

makeSum(ar,5,&sum);

・・・

void makeSum(int *ap, int n, int *sp){

*sp=0;

for(int i=0; i<n; i++) *sp+=*ap++;

}

4 6 2 3 1

ar

sum

main関数 makeSum関数

ap n sp

5 0

i

012345

4 10 12 15 16

この処理は

*sp+=*ap;

ap++;

と同じである。

参照

関連したドキュメント

&lt;Point&gt; MIN 関数の書式:=MIN(p1:p2) 【MIN

pthread による行列計算の高速化の試み 231 自己列の先頭アドレスを a とすると EA= α+i

行列多項式 $I+A+A^{2}+\cdots+A^{N-1}$ の計算における 行列乗算回数 松本 耕太朗 $*$ 高木 1 はじめに 行列多項式 $G(N, A)=I+A+A^{2}+\cdots+A^{N-1}$

kadai4_6

[r]

本研究では並列計算の有用性を示すために、 MPI を用 いて以下の計算を行う。行列計算を1つのコンピュータ で計算する場合と、

さて、前節と同様に、ここでも当然、行列の基本的演算は関数化しておきたい所であるが、多次元配列の場 合は通常の1次元の配列の時にはなかった問題がある。 行横の並び: row 列縦の並び: column C言語の多次元配列はあくまでも「配列の配列」であって、例えば行列を扱う為に int a[ROWS][COLUMNS]; と宣言した場合、 a[i]は「int

3×3 行列に関する基本的な関数表示・演算などを作成して実習14.3 のプログラムを書き直し た次頁のプログラムmatrix2.cを完成させよ。 行列の積を計算する関数 multmatrix の実装例は保留する。更に考えられたい。 Check Point: • 動作確認をきちんと行なったか。 • 表示・演算などを関数化している か。 •