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

ポインタと配列

N/A
N/A
Protected

Academic year: 2021

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

Copied!
4
0
0

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

全文

(1)

ポインタと配列

理工学部 情報科学科 上級プログラミング

ポインタの復習

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

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

ポインタはアド レスを代入して 初めて使える

ポインタの復習

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

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

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

配列とアドレス

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

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]

のどちらでも表せる。

(2)

配列とポインタ(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

++で1つ分p

進む --で1つ分 戻る

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

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

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

配列とポインタ(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;

どれも同じ 代入

配列とポインタ(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;

どちらも 同じ代入

ポインタ間の演算

◎同じ型の2つのポインタの差は定義されている

int a[8];

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

このあと、例えば

p2-p1

という計算は可能

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

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

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

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

同一配列内の要素へのポインタの差のみ計算は有効 上記の例で、p2-p1の値は5となる

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

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

(3)

二次元配列のアドレス

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*

コマンドラインの取得

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

comsv% example inputfile.txt 12 abc

この部分を受け取るのが

main

関数の引数

コマンド プロンプト

と呼ぶ

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

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

コマンドラインの取得

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

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の文字)で終わる。

関数への配列渡し(例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

(4)

関数への配列渡し(例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

関数への配列渡し(例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++;

と同じである。

参照

関連したドキュメント

“Breuil-M´ezard conjecture and modularity lifting for potentially semistable deformations after

0.1uF のポリプロピレン・コンデンサと 10uF を並列に配置した 100M

[r]

( 内部抵抗0Ωの 理想信号源

○○でございます。私どもはもともと工場協会という形で活動していたのですけれども、要

16 単列 GIS配管との干渉回避 17 単列 DG連絡ダクトとの干渉回避 18~20 単列 電気・通信ケーブル,K排水路,.

4 マトリックス型相互参加における量的 動をとりうる限界数は五 0

名称 「食べ残しゼロ協力店」登録制度 対象 名古屋市内の飲食店及び宿泊施設 登録要件