02: 変数と標準入出力

Similar documents
02: 変数と標準入出力

02: 変数と標準入出力

02: 変数と標準入出力

02: 変数と標準入出力

02: 変数と標準入出力

02: 変数と標準入出力

02: 変数と標準入出力

02: 変数と標準入出力

memo

PowerPoint プレゼンテーション

02: 変数と標準入出力

02: 変数と標準入出力

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

02: 変数と標準入出力

Microsoft PowerPoint pptx

02: 変数と標準入出力

02: 変数と標準入出力

PowerPoint プレゼンテーション

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

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

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

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

PowerPoint プレゼンテーション

Microsoft PowerPoint - 09.pptx

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

概要 プログラミング論 変数のスコープ, 記憶クラス. メモリ動的確保. 変数のスコープ 重要. おそらく簡単. 記憶クラス 自動変数 (auto) と静的変数 (static). スコープほどではないが重要.

Microsoft Word - 3new.doc

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

Microsoft PowerPoint - H22プログラミング第一(E)#12

memo

memo

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

program7app.ppt

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

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

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

Microsoft PowerPoint - C++_第1回.pptx

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

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

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

関数の中で宣言された変数の有効範囲はその関数の中だけです さっきの rectangle _s で宣言されている変数 s は他の関数では使用できません ( 別の関数で同じ名前の変数を宣言することはできますが 全く別の変数として扱われます このように ある関数の中で宣言されている変数のことをその関数の

プログラミング実習I

第2回

情報処理 Ⅱ 2007 年 11 月 26 日 ( 月 )

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

gengo1-11

Prog1_10th

Microsoft PowerPoint - 11.pptx

Microsoft PowerPoint pptx

講習No.9

プログラミングI第10回

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

プログラミング実習I

Microsoft PowerPoint pptx[読み取り専用]

Microsoft PowerPoint - kougi7.ppt

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

CプログラミングI

Microsoft PowerPoint pptx

Microsoft PowerPoint - lec10.ppt

Microsoft PowerPoint ppt

PowerPoint Presentation

PowerPoint プレゼンテーション

関数の動作 / printhw(); 7 printf(" n"); printhw(); printf("############ n"); 4 printhw(); 5 関数の作り方 ( 関数名 ) 戻り値 ( 後述 ) void である. 関数名 (

目次

Prog1_12th

Microsoft Word - no15.docx

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

計算機プログラミング


Microsoft PowerPoint - prog03.ppt

2006年10月5日(木)実施

kiso2-09.key

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

情報処理演習 B8クラス

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

Microsoft Word - no202.docx

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

Microsoft Word - 第5回 基本データ構造2(連結リスト).doc

1 return main() { main main C 1 戻り値の型 関数名 引数 関数ブロックをあらわす中括弧 main() 関数の定義 int main(void){ printf("hello World!!\n"); return 0; 戻り値 1: main() 2.2 C main

関数の呼び出し ( 選択ソート ) 選択ソートのプログラム (findminvalue, findandreplace ができているとする ) #include <stdiu.h> #define InFile "data.txt" #define OutFile "surted.txt" #def

講習No.10

gengo1-10

プログラミング演習3 - Cプログラミング -

gengo1-12

PowerPoint プレゼンテーション

プログラミング方法論 II 第 14,15 回 ( 担当 : 鈴木伸夫 ) 問題 17. x 座標と y 座標をメンバに持つ構造体 Point を作成せよ 但し座標 は double 型とする typedef struct{ (a) x; (b) y; } Point; 問題 18. 問題 17 の

講習No.12

Microsoft Word - 03

cp-7. 配列

PowerPoint プレゼンテーション

Microsoft PowerPoint - 5Chap15.ppt

<4D F736F F D20438CBE8CEA8D758DC F0939A82C282AB2E646F63>

PowerPoint プレゼンテーション

AquesTalk プログラミングガイド

ポインタ変数

ARToolKit プログラムの仕組み 1: ヘッダファイルのインクルード 2: Main 関数 3: Main Loop 関数 4: マウス入力処理関数 5: キーボード入力処理関数 6: 終了処理関数 3: Main Loop 関数 1カメラ画像の取得 2カメラ画像の描画 3マーカの検出と認識

<4D F736F F D20438CBE8CEA8D758DC03389F0939A82C282AB2E646F63>

基礎プログラミング2015

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

JavaプログラミングⅠ

Transcription:

C プログラミング入門 基幹 7 ( 水 5) 11: 動的メモリ確保 Linux にログインし 以下の講義ページを開いておくこと http://www-it.sci.waseda.ac.jp/ teachers/w483692/cpr1/ 2016-06-22 1

まとめ : ポインタを使った処理 内容呼び出し元の変数を書き換える文字列を渡す 配列を渡すファイルポインタ複数の値を返す大きな領域を確保する 説明第 9 回第 10 回第 10 回今回今回 2

ポインタの扱い 3

return は 1 つの値しか返せない 複数返すには 書きこんでもらいたい変数へのポインタを渡す 返り値を使って計算 複数の値を返す 例 :int 配列の最大 最小値を計算する int maximum(const int *a, int n); int minimum(const int *a, int n); 整数の配列の先頭ポインタとその個数 void minmax(const int *a, int n, int *m, int *M); 返り値を使わない ( 使ってもいい ) 最小値を書き込むアドレス ( 変数などへのポインタ ) 書き換えるので const がつかない 最大値を書き込むアドレス ( 変数などへのポインタ ) 4

標準ライブラリ関数の例 整数部と小数部を求める関数 double modf(double value, double *iptr); 戻り値 :value の小数部 ( 符号付き ) iptr の指すメモリ領域 : 整数部 ( 符号付き ) #include <stdio.h> #include <math.h> int main(void) double ipart, fpart; fpart = modf(32.5, &ipart); 小数部 0.5 は戻り値として返る double ipart 32 double fpart 0.5 変数 ipart のアドレスを渡すことで 関数 modf は ipart の中身を書き換えることができる 5

ポインタ変数の初期値の注意 通常の変数同様 ポインタ変数も初期化されない しかし どこかは指している 初期化しないポインタ変数でアクセスすると危険 int *p; // 初期化なし *p = 100; 暗黙の初期化はされないので どこを指すアドレスが入っているかは不明 p 6

NULL ポインタによる安全策 以下の場合 null ポインタを入れるとよい 初期化ではアドレスを決定しない 今まで使っていたアドレス無効になった null ポインタを通したアクセスは発見しやすい ポインタ変数の値 ( アドレス ) が null ポインタの場合 斜線 int *p = NULL; を引いて どこも指示していないことを表現することがおおい *p = 100; null ポインタが指す領域にアクセスすると システムが検知して 例外を発生する p 7

どのアドレスでもないことを示す特別な値 空ポインタともいう null ポインタ null ポインタに対してデリファレンス演算子 * を使うと例外 (null pointer exception) が発生する null ポインタ定数マクロ NULL を使って判定する 数値リテラル 0 は null ポインタに変換される <stddef.h> で定義されているが <stdio.h> などで自動的にインクルードされる 8

null ポインタ判定 以下のような書き方のバリエーションがある p が null であるか p が null でないか if(p == NULL) if(p!= NULL) if(p == 0) if(p!= 0) if(!p) if(p) if は常に式の評価値が 0 でないことを判定するので 上段の式と同じ意味になる 9

メモリ領域を作成する 10

基本型を返す関数... double trace3(const double Mat[3][3]) double tr = Mat[0][0]+Mat[1][1]+Mat[2][2]; return tr; } double 型などの基本型を戻り値とする関数は簡単に作れる int main(void) double Mat[3][3] = 1, 2, 3 }, 4, 5, 6 }, 7, 8, 9 } }; trace3(mat); // => 15 値そのものがコピーをされて伝搬していく 11

... int* seq3(int a) int s[] = a, a+1, a+2 }; return s; } 配列を返す関数? 配列のコピーはできないので 配列の先頭へのポインタを返す? int main(void) int *seq = seq3(10); 配列の先頭へのポインタを受け取る? seq[0]; // => 10? seq[1]; // => 11? seq[2]; // => 12? この方法ではうまくいかない 12

関数内の配列のアドレスを返してはいけない 関数内で定義された配列変数は 通常の変数と同様に関数の実行が終了する際に消滅する... unsigned char *createnewimage(void) unsigned char img[512*512] = 0 }; return img; } このポインタ ( アドレス ) の指す領域はもうない int main(void) unsigned char *pimage;... pimage = createnewimage(); // この後ポインタ pimage を使って // アクセスしてはいけない 配列の型を戻り値とする関数は作れないその代わり ポインタを返す createnewimage の領域この領域は関数の実行後 img 消滅してしまう pimage 13

自動的に消滅しないメモリ領域を作る 動的メモリ確保 (dynamic memory allocation) 変数のような言語機能ではなく 標準ライブラリ関数を使って 直接 OS にメモリ領域を要求する 確保された領域は自由に使える 変数名はつかないので ポインタでアクセスする 自動的には消去されないので 自分で解放する 14

動的メモリの確保 malloc() 関数によって指定したバイト数のメモリ領域を確保する メモリ領域は初期化されない メモリ不足などで確保が失敗した場合 NULL ポインタが返る 確保された領域が置かれているところをヒープ (heap) という malloc() のプロトタイプ #include <stdlib.h> void *malloc(size_t size); 次のスライドで説明 15

確保されたメモリ領域の値 malloc は void * 型を返す 特定の型を表さない 任意のポインタ型に自動変換できる int *pint; double *pdouble; ヒープ領域 C++ では自動変換されないため static_cast が必要 100??????????? 3.14 pint = malloc(16); pint[0] = 100; // double の場合 // pdouble = malloc(16); // pdouble[0] = 3.14; sizeof(int) == 4, sizeof(double) == 8 の場合 int *pint 指し示すアドレスは同じだが 扱われ方が型によって異なる?? main のスタック領域 double *pdouble 16

サイズの指定 例 : int 型の 100 個の領域を確保 int *mem = malloc(sizeof(int) * 100); mem[0] ~ mem[99] としてアクセス 17

例 : 画素値を unsigned char 型として w h のサイズのメモリ領域を確保 unsigned char *image = malloc(sizeof(unsigned char) * w * h); 座標 x, y に対して image[x+y*w] としてアクセス w 0 x < w, 0 y < h サイズの指定 image[0+0*w] sizeof(unsigned char) は必ず 1 なので 書かなくてもよい h image[x+y*w] 18

動的メモリの確保 ( その他 ) calloc(): malloc() と同じだが さらにゼロで初期化を行う size num バイトの領域を確保する メモリの全てのビットが 0 となるからと言って double などの型の値として 0 となるとは限らない realloc(): 確保された領域のサイズを変更 calloc(), realloc() のプロトタイプ #include <stdlib.h> void *calloc(size_t num, size_t size); void *realloc(void *ptr, size_t new_size); 19

確保したメモリへのポインタを指定して その領域を解放する 解放した領域は使用してはならない NULL を入れておくと安全 既に解放済みのポインタに対して実行してはいけない (2 重解放エラー ) NULL ポインタを与えた場合は何もしない free() のプロトタイプ 動的メモリの解放 #include <stdlib.h> void free(void* ptr); どんな型のポインタも void * に自動的に変換される 20

例題 :PGM 画像 画像のためのメモリを自動的に確保する関数... // 画素値 0 で初期化された画像を動的に作成する unsigned char *createimage(int width, int height) int i; unsigned char *img = malloc(width * height); if(img == NULL) sizeof(unsigned char) == 1 な ので 掛けるのを省略 return NULL; } メモリ不足の場合は NULL を返す for(i = 0; i < width*height; ++i) img[i] = 0; return img; } すべてゼロで初期化する 21

例題 :PGM 画像 使い終わったら自分で free() する... int main(void) unsigned char *Image = NULL;... Image = createimage(640, 480);... free(image), Image = NULL; メモリ領域を解放する ポインタは無効になるので NULL ポインタを代入しておくとよい 22

用語 : メモリリーク (memory leak) malloc() で動的確保した領域を free() で解放し忘れて メモリが圧迫されること 単純なプログラムではこの手のバグは見つけやすいが 秋期 C プログラミング で扱う複雑なデータ構造では発生しやすく 見つけづらいバグとなる 23

変数とポインタと動的メモリ確保の整理 メモリに領域を確保して値を読み書きする方法には 4 つある 分類生存期間スコープメモリ領域初期化 自動変数 ( ローカル変数 ) 大域変数 ( グローバル変数 ) 静的変数 (static 変数 ) 動的メモリ 定義位置からブロック終端まで プログラムの実行開始から終了まで プログラムの実行開始から終了まで 確保から解放まで 定義位置からブロック終端まで 定義位置からプログラム終了まで 定義位置からブロック終端まで スタック 静的領域 静的領域 ヒープ 初期化が指定されている場合のみ ブロックに入るたびに初期化される プログラム開始時に 1 度だけ 初期化が指定されない場合 0 で初期化される 同上 malloc() はされない calloc() は 0 を書きこむ 変数名で参照しない 24

配列変数と動的メモリ確保の比較 機能配列動的メモリ確保 サイズ 多次元 自動変数の場合は あまり大きなサイズは確保できない 可能 ただし 関数などに次元やサイズを伝えられない ほとんど制限がない 単なるポインタなので不可能 コピー不可能 標準ライブラリ関数を利用不可能 標準ライブラリ関数を利用 解放 アクセス 自動変数の場合 ブロックを抜けると自動的に消滅する 変数名が先頭へのポインタになる free() によって自分で解放する malloc() によって得られるアドレスをポインタ変数に入れて扱う 25