プログラミングI第5回

Similar documents
プログラミングI第6回

Microsoft Word - 3new.doc

プログラミングI第10回

02: 変数と標準入出力

02: 変数と標準入出力

Prog1_10th

02: 変数と標準入出力

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

プログラミングI第11回

7 ポインタ (P.61) ポインタを使うと, メモリ上のデータを直接操作することができる. 例えばデータの変更 やコピーなどが簡単にできる. また処理が高速になる. 7.1 ポインタの概念 変数を次のように宣言すると, int num; メモリにその領域が確保される. 仮にその開始のアドレスを 1

第1回 プログラミング演習3 センサーアプリケーション

Microsoft PowerPoint - 5Chap15.ppt

02: 変数と標準入出力

PowerPoint Presentation

02: 変数と標準入出力

PowerPoint プレゼンテーション

Microsoft Word - no202.docx

< F2D837C E95CF CF68A4A94C5816A2E6A>

メソッドのまとめ

PowerPoint プレゼンテーション

memo

PowerPoint プレゼンテーション

4 月 東京都立蔵前工業高等学校平成 30 年度教科 ( 工業 ) 科目 ( プログラミング技術 ) 年間授業計画 教科 :( 工業 ) 科目 :( プログラミング技術 ) 単位数 : 2 単位 対象学年組 :( 第 3 学年電気科 ) 教科担当者 :( 高橋寛 三枝明夫 ) 使用教科書 :( プロ

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

PowerPoint プレゼンテーション

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

情報処理Ⅰ演習

また 初期化について 以下のサンプルコードのように指定すれば 定義時に値を代入できます * オマケ配列は同名で複数個の箱を用意出来ます 同名ではありますが それぞれは別々の個体であるわけです また この複数個の変数は メモリ上に連続で確保されます 2. 文字と文字列 C 言語では文字と文字列は異なる

PowerPoint プレゼンテーション

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

Microsoft PowerPoint - 11.pptx

プログラミング実習I

ポインタ変数

デジタル表現論・第6回

CプログラミングI

Microsoft PowerPoint - 計算機言語 第7回.ppt

Microsoft PowerPoint - 09.pptx

目次

memo

Microsoft PowerPoint pptx

gengo1-11

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

3,, となって欲しいのだが 実際の出力結果を確認すると両方の配列とも 10, 2, 3,, となってしまっている この結果は代入後の配列 a と b は同じものになっていることを示している つまり 代入演算子 = によるの代入は全要素のコピーではなく 先をコピーする ため 代入後の a と b は

講習No.9

Microsoft PowerPoint - ruby_instruction.ppt

PowerPoint プレゼンテーション - 物理学情報処理演習

Microsoft PowerPoint - prog03.ppt

PowerPoint プレゼンテーション

(2) 構造体変数の宣言 文法は次のとおり. struct 構造体タグ名構造体変数名 ; (1) と (2) は同時に行える. struct 構造体タグ名 { データ型変数 1; データ型変数 2;... 構造体変数名 ; 例 : struct STUDENT{ stdata; int id; do

Microsoft Word - Cプログラミング演習(12)

02: 変数と標準入出力

02: 変数と標準入出力

kiso2-09.key

情報処理演習 B8クラス

gengo1-8

02: 変数と標準入出力

Java プログラミング Ⅰ 3 回目変数 変数 変 数 一時的に値を記憶させておく機能型 ( データ型 ) と識別子をもつ 2 型 ( データ型 ) 変数の種類型に応じて記憶できる値の種類や範囲が決まる 型 値の種類 値の範囲 boolean 真偽値 true / false char 2バイト文

今までの復習 プログラムで最低限必要なもの 入力 ( キーボードから ファイルから ) 出力 ( 画面へ ファイルへ ) 条件分岐 : 条件の成立 不成立により 異なる動作をする 繰り返し : 一定の回数の繰返し 条件成立の間の繰返し 関数の定義 関数の呼び出し C ではそれ以外に ポインタ データ

02: 変数と標準入出力

JavaプログラミングⅠ

Microsoft PowerPoint - handout07.ppt [互換モード]

<4D F736F F D2091E63589F182628CBE8CEA8D758DC08E9197BF2E646F6378>

プログラミング及び演習 第1回 講義概容・実行制御

gengo1-12

memo

char int float double の変数型はそれぞれ 文字あるいは小さな整数 整数 実数 より精度の高い ( 数値のより大きい より小さい ) 実数 を扱う時に用いる 備考 : 基本型の説明に示した 浮動小数点 とは数値を指数表現で表す方法である 例えば は指数表現で 3 書く

プログラミング基礎

FORTRAN( と C) によるプログラミング 5 ファイル入出力 ここではファイルからデータを読みこんだり ファイルにデータを書き出したりするプログラムを作成してみます はじめに テキスト形式で書かれたデータファイルに書かれているデータを読みこんで配列に代入し 標準出力に書き出すプログラムを作り

Prog1_6th

gengo1-2

program7app.ppt

Microsoft PowerPoint - CproNt11.ppt [互換モード]

Microsoft Word - no02.doc

ファイル入出力

<4D F736F F D20438CBE8CEA8D758DC F0939A82C282AB2E646F63>

PowerPoint プレゼンテーション

Microsoft PowerPoint - prog03.ppt

2014_H01-04_JP

Microsoft PowerPoint - chap10_OOP.ppt

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

基礎プログラミング2015

Microsoft PowerPoint pptx

ファイル入出力

Taro-ポインタ変数Ⅰ(公開版).j

Microsoft Word _VBAProg1.docx

PowerPoint プレゼンテーション

Microsoft PowerPoint pptx

演算増幅器

Microsoft PowerPoint - prog04.ppt

System.out.println("char : " + (int)character.min_value + "~" + (int)character.max_value); System.out.println("float : " + Float.MIN_VALUE + "~" + Flo

情報工学実験 C コンパイラ第 2 回説明資料 (2017 年度 ) 担当 : 笹倉 佐藤

Microsoft PowerPoint - 13th.ppt [互換モード]

pp2018-pp9base

gengo1-12

PowerPoint Presentation

Microsoft Word - no11.docx

6 関数 6-1 関数とは少し長いプログラムを作るようになると 同じ処理を何度も行う場面が出てくる そのたびに処 理を書いていたのでは明らかに無駄であるし プログラム全体の見通しも悪くなる そこで登場す るのが 関数 である 関数を使うことを 関数を呼び出す ともいう どのように使うのか 実際に見て

スライド 1

問 2 ( 型変換 ) 次のプログラムを実行しても正しい結果が得られない 何が間違いかを指摘し 正しく修正せよ ただし int サイズが 2 バイト long サイズが 4 バイトの処理系での演算を仮定する #include <stdio.h> int main( void ) { int a =

Transcription:

プログラミング 第 5 回 ポインタ () -- ポインタ演算 配列のアドレス ポインタ演算 ( 前期教科書 P77~) ポインタと配列 ( 同上 P8) 文字列定数と文字列配列 ( 同上 P85) この資料にあるサンプルプログラムは /home/course/rog/ublc_html/7/hw/lec/sources/ 下に置いてありますから 各自自分のディレクトリにコピーして コンパイル 実行してみてください Prog- 7 Lec 5- Programmng- Grou 999-7

配列のアドレス これまで単体の変数でアドレスを考えてきたが 配列の場合はどうであろうか? まず 配列の要素アドレスはそれぞれの要素の前に & を付加することで知ることが出来る 下の例の中では 配列 str の 番目の要素のアドレスは &str[] である ついでに配列名そのものの値も出力してみて 右の結果からわかるように 配列名は最初の要素のアドレスと一緒であった 実は これは偶然ではない ( これは後ほど述べる ) #nclude #nclude man() man() nt nt str[] str[] "u-azu" "u-azu" for( for( 6 ++) ++) rntf("%d rntf("%d % % %c\n",, %c\n",, &str[],str[]) rntf("\n%\n",str) 実行結果実行結果 : : sstdss: sstdss: effff9d effff9d u u effff9d effff9d - - effff9d effff9d a a effff9d effff9d effff9d effff9d z z 5 5 effff9d5 effff9d5 u u effff9d effff9d sstdss: sstdss: アドレスは環境によって違うが 要素のアドレスの差に注目 Prog- 7 Lec 5- Programmng- Grou 999-7

配列のアドレス 前の例において 文字型の配列 ( 本当は 文字列 ) であったが 他の型の配列も同じように考えられる long 型の場合は以下のようになる #nclude #nclude man() man() nt nt long long array[] array[],,,,,, for( for( ++) ++) rntf( rntf( "%d "%d % % %d\n",,&array[],array[]) %d\n",,&array[],array[]) rntf("\n%\n",array) rntf("\n%\n",array) 実行結果実行結果 sstdss: sstdss: effff9c8 effff9c8 effff9cc effff9cc effff9d effff9d effff9d effff9d effff9c8 effff9c8 sstdss: sstdss: アドレスは環境によって違うが 要素のアドレスの差に注目 Prog- 7 Lec 5- Programmng- Grou 999-7

アドレスの飛び方 文字型とlong 型で分かる通り 配列の各要素は型の大きさ分だけアドレスが離れている 各型の大きさを再掲する この値は会津大学の標準的な環境での値である 型 大きさ ( バイト数 ) イメージ short nt,float, ポインタ double 8 Prog- 7 Lec 5- Programmng- Grou 999-7

アドレスの飛び方 イメージ的には以下のようになる 型 (バイト) long 型 (バイト) 要素 要素 要素 配列の各要素は型の大きさ分だけアドレスが離れている ( 添字 の要素のアドレスが一番小さい ) Prog- 7 Lec 5-5 Programmng- Grou 999-7

ポインタ演算 ポインタ演算 ( 加算 減算 ) を以下のように取り決める ポインタに を加える ( 減じる ) とは ポインタが保持するアドレスに型の大きさ (long なら ) を加える ( 減じる ) ことである 先ほどの long の例において long 型のポインタの値が配列の先頭要素 ( 要素 ) のアドレス つまり &array[] だとすると 以下のようになる ポインタアドレス要素 &array[] effff9c8 array[] + &array[] effff9cc array[] + &array[] effff9d array[] Prog- 7 Lec 5-6 Programmng- Grou 999-7

ポインタ演算例 ポインタ演算を利用すると以下のようなプログラムを書くことが出来る #nclude #nclude man() man() nt nt,, a[] a[],,,,,, nt nt * *,*q,*q 実行結果実行結果 sstdss: sstdss: sstdss: sstdss: for( for( ++) ++) rntf("%d rntf("%d ",a[]) ",a[]) rntf("\n") rntf("\n") &a[] &a[] /* /* a a の最初の要素のアドレスを最初の要素のアドレスを に代入するに代入する */ */ for( for( ++) ++) rntf("%d rntf("%d ",*( ",*( + + )) )) rntf("\n") rntf("\n") for(q for(q q q + + q++) q++) rntf("%d rntf("%d ",*q) ",*q) rntf("\n") rntf("\n") 配列 a Prog- 7 Lec 5-7 Programmng- Grou 999-7

ポインタ演算例 文字列操作の例 #nclude #nclude 実行結果実行結果 man() man() a z u \o sstdss: sstdss: azu azu nt nt azu azu str[] str[] "azu" "azu" azu azu * *,*q,*q は &str[] 正順出力 uza ( 配列の先頭 ) uza uza を指す uza &str[] &str[] sstdss: sstdss: for( for( str[] str[]!! '\' '\' ++) ++) rntf("%c",str[]) rntf("%c",str[]) rntf("\n") rntf("\n") for( for( *( *( + + ) )!! '\' '\' ++) ++) rntf("%c",*( rntf("%c",*( + + )) )) rntf("\n") rntf("\n") for(q for(q *q *q!! '\' '\' q++) q++) rntf("%c",*q) rntf("%c",*q) rntf("\n") rntf("\n") a z u \o にヌル文字の逆順出力ループ終了時には q q アドレスを代入 qはヌル文字のアド q for( for( - - > > &str[] &str[] ++) ++) rntf("%c",*( rntf("%c",*( - - )) )) レスが入っている rntf("\n") rntf("\n") for(q for(q - - q q > > &str[] &str[] q--) q--) rntf("%c",*q) rntf("%c",*q) rntf("\n") rntf("\n") Prog- 7 Lec 5-8 Programmng- Grou 999-7

配列名とは 文字列の場合 rntf など関数への引数として配列名を渡す 配列名とはいったい何なのだろうか? これまでのプログラムの実行結果で分かる通り 配列名が保持する値は実は最初の要素のアドレスである つまり配列名とは配列の最初の要素を指すポインタのようなものである (str &str[]) 逆に次ページの例のように ポインタを配列のように使用することも可能である Prog- 7 Lec 5-9 Programmng- Grou 999-7

配列名とポインタ #nclude #nclude man() man() nt nt, a[] a[],,,,,, nt nt * * a a /* /* つまりこれはつまりこれは &a[] &a[] と同じ事と同じ事 */ */ 実行結果実行結果 sstdss: sstdss: sstdss: sstdss: for( for( ++) ++) rntf("%d rntf("%d ",a[]) ",a[]) rntf("\n") rntf("\n") for( for( ++) ++) rntf("%d rntf("%d ",[]) ",[]) rntf("\n") rntf("\n") for( for( ++) ++) rntf("%d rntf("%d ",*(a ",*(a + )) )) rntf("\n") rntf("\n") for( for( ++) ++) rntf("%d rntf("%d ",*( ",*( + )) )) rntf("\n") rntf("\n") 配列風 ポインタ風 Prog- 7 Lec 5- Programmng- Grou 999-7

配列とポインタの相違点 配列とポインタは極めて類似していることが分かった しかし相違点もある 配列は実際に領域を確保する ( 正確には要素数 型の大きさバイトの領域 ) のに対して ポインタはポインタ変数の分 ( 会津大学の通常の環境ではバイト ) だけしか確保しない ポインタは適切に初期化しない限り配列の代用にはならない 逆にポインタは適切に初期化すれば配列の代用になると言う事も出来る ポインタは同型の変数や 配列をどれを指してもかまわないが 配列名は指定されているメモリ領域しか指すことができず その値を変更することはできない つまり 配列名は ポインタ定数である Prog- 7 Lec 5- Programmng- Grou 999-7

配列とポインタの相違点 配列名はアドレス定数であるので その値 ( アドレス値 ) を変更 ( 代入 ) 出来ない #nclude #nclude man() man() nt nt a[5],,,,5 a[5],,,,5 nt nt 配列配列 コンパイルエラー コンパイル結果コンパイル結果 : : In In functon functon `man': `man': : : wrong wrong tye tye argument argument to to ncrement ncrement for( for( 5 5 ++) ++) rntf("%d\n", rntf("%d\n", *a++) *a++) #nclude #nclude man() man() ポインタポインタ nt nt a[5],,,,5, a[5],,,,5, * * nt nt a a for( for( 5 5 ++) ++) rntf("%d\n", rntf("%d\n", *++) *++) アドレスが指し示すデータの内容を rntf に渡した後で アドレスをインクリメント (nt なので +) することを意味する コンパイル 実行可能! [] のように書いても良い Prog- 7 Lec 5- Programmng- Grou 999-7

配列とポインタの相違点 ポインタに対して定数初期化は出来ない 配列は要素の個数分メモリ領域に実際に変数領域が確保される 一方ポインタを配列の代わりに使用しても 実際には領域の確保は行われない 従って下例のようにポインタに対して初期化することは出来ない #nclude #nclude man() man() ポインタ ポインタ nt nt,*,,,,5,*,,,,5 for( for( 5 5 ++) ++) rntf("%d\n", rntf("%d\n", []) []) 警告 コンパイル結果コンパイル結果 : : warnng: warnng: ntalzaton ntalzaton makes makes onter onter from from nteger nteger wthout wthout a a cast cast : : warnng: warnng: excess excess elements elements n n scalar scalar ntalzer ntalzer after after `' `' #nclude #nclude man() man() 配列 配列 nt nt,a[],,,,5,a[],,,,5 for( for( 5 5 ++) ++) rntf("%d\n", rntf("%d\n", a[]) a[]) コンパイル 実行可能! 実行すると エラー Prog- 7 Lec 5- Programmng- Grou 999-7

配列とポインタの相違点 文字列 ( 文字ポインタ ) の場合のみポインタに定数初期化が出来る 文字列ポインタの初期化は 定数領域に文字列データが格納され そのアドレスをポインタが指し示すことで行なう #nclude #nclude man() man() a[]"abc" a[]"abc" rntf("%s\n",a) rntf("%s\n",a) 配列配列 コンパイル 実行可能! #nclude #nclude man() man() *"ABC" *"ABC" rntf("%s\n",) rntf("%s\n",) ポインタポインタ コンパイル 実行可能! Prog- 7 Lec 5- Programmng- Grou 999-7

文字列定数の変更 文字列定数はポインタの初期化で宣言する 文字列定数は通常メモリの書き込み禁止領域に領域が取られる このため通常の文字列と異なり 文字列定数の変更は出来ない #nclude #nclude man() man() *"ABC" *"ABC" [] [] 'Z' 'Z' rntf("%s\n",) rntf("%s\n",) 文字 'Z' 実行結果 ( 実行結果はマシンによって異なる ) Segmentaton fault A B C \ 書き込み禁止領域 Prog- 7 Lec 5-5 Programmng- Grou 999-7

配列とポインタの相違点 ( まとめ ) 配列とポインタの違いを表にまとめる (a を配列名 をポインタだとする ) 操作 ポインタ 配列 代入 a a インクリメント ++ a++ 加減算 + a + Prog- 7 Lec 5-6 Programmng- Grou 999-7

文字列定数配列とポインタ配列 文字列定数の配列はポインタの配列として定義出来る #nclude #nclude man() man() *str[] *str[] "Tokyo","Nagoya","Osaka","Azu" "Tokyo","Nagoya","Osaka","Azu" nt nt for( for( ++) ++) rntf("%s\n",str[]) rntf("%s\n",str[]) 実行結果実行結果 sstdss: sstdss: Tokyo Tokyo Nagoya Nagoya Osaka Osaka Azu Azu sstdss: sstdss: Prog- 7 Lec 5-7 Programmng- Grou 999-7

文字列配列とポインタ配列 この時のポインタと文字列定数の関係は以下の通り 文字列としては str[] のように表す ( 番目の文字列を示す ) 文字としては str[][] のように表す ( 番目の文字列中 番目の文字を示す ) ポインタ配列 str str[] str[] str[] str[] T o k y o \ N a g o y a \ O s a k a \ A z u \ 書き込み禁止領域 書 Prog- 7 Lec 5-8 Programmng- Grou 999-7

文字列配列を配列で組むと この場合は文字列 変数 となるので 自由に代入を行うことが出来る 文字列としては str[] のように表す ( 番目の文字列を示す ) str[] は &str[][] と等しい 文字としては str[][] のように表す ( 番目の文字列中 番目の文字を示す ) #nclude #nclude man() man() str[][8] str[][8] "Tokyo","Nagoya","Osaka","Azu" "Tokyo","Nagoya","Osaka","Azu" nt nt strcy(str[],"saoro") strcy(str[],"saoro") /* /* 文字列の代入可能文字列の代入可能! */ */ for( for( ++) ++) rntf("%s\n",str[]) rntf("%s\n",str[]) 文字列として表示 for( for( str[][] str[][]!! '\' '\' ++) ++) rntf("%c\n",str[][]) rntf("%c\n",str[][]) 文字として縦表示 実行結果実行結果 sstdss: sstdss: Tokyo Tokyo Nagoya Nagoya Saoro Saoro A A z z u u sstdss: sstdss: Prog- 7 Lec 5-9 Programmng- Grou 999-7

二次元文字配列 初期化時の二次元文字配列の状態は以下の通り &str[][]:str[] &str[][]:str[] &str[][]:str[] &str[][]:str[] T o k y o \ N a g o y a \ O s a k a \ A z u \ 変数領域 の領域は何が入っているか不定 Prog- 7 Lec 5- Programmng- Grou 999-7