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

02: 変数と標準入出力

N/A
N/A
Protected

Academic year: 2021

シェア "02: 変数と標準入出力"

Copied!
28
0
0

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

全文

(1)

14: 発展事項

2014-07-13

C プログラミング入門

総機1 (月1)

(2)

これまでの講義で説

明していない事項に

ついていくつか簡単

に紹介する

 文法  標準入出力ファイル  異常終了  短絡評価  文字定数の型  キャスト  変数の宣言位置  グローバル変数  静的変数 (static)  const 変数  プリプロセッサ・ディレクティブ  マクロ  ファイルの読み込み  数学関数のエラーチェック  関数ポインタ  可変長引数  プログラミング技術  モジュールプログラミング  外部リンケージ  アサーション 2014-07-13 C プログラミング入門 総機1 (月1)

2

今日の内容

(3)

文法

(4)

標準入力、標準出力はファイルの一種

それぞれ stdin, stdout という FILE ポインタが

グローバル変数で定義されている

たとえば printf("Hello!"); は

fprintf(stdout, "Hello!); と同じ

標準エラー出力というのもある

fprintf(stderr, "Memory error¥n");

標準出力とは区別されていて、エラーを知らせる 時に使う。標準出力がリダイレクトされてもエラー は画面に出る 2014-07-13 C プログラミング入門 総機1 (月1)

4

標準入出力

<stddef.h> で定 義されているが、 <stdio.h> などで 読み込まれている

(5)

main()

から return で終了した場合を正常終

了という

標準ライブラリ関数 exit() を使っても同じ 終了時に自動的に呼ばれる関数を atexit() で登 録することができる

OS による検出などで強制的に終了すること

を異常終了という

プログラムから意図的に行うには abort() を用い る シグナルをトラップして処理できる(詳細略) 2014-07-13 C プログラミング入門 総機1 (月1)

5

正常終了・異常終了

(6)

論理演算子の最初の式から全体の値が決まる場合、

2

つ目の式を評価しない

(式1) && (式2) : (式1) が偽の場合、(式2) を評価し ない (式1) || (式2) : (式1) が真の場合、(式2) を評価し ない

たとえば、以下のような場合に意味を持つ

if(p != NULL && p[0] == 3) …

もし p が null ポインタの場合、 p[0] は評価できないが、 短絡評価されるので問題ない 2014-07-13 C プログラミング入門 総機1 (月1)

6

短絡評価

式全体として偽となる 式全体として真となる もちろん、 if(p != NULL) { if(p[0] == 3) ... } と書いてもよい

(7)

文字定数 (文字リテラル) は char 型ではなく、

int

型である

例: 'A' は ASCII コードでは int の 65

標準ライブラリ関数で文字を扱う関数では、

文字を指定するのに int 型となっている

例: 指定した文字 ch を文字列 str から見つける

char *strchr(const char *str, int ch);

2014-07-13 C プログラミング入門 総機1 (月1)

7

文字定数の型

(8)

数値を任意の型に強制的に変換する

変換されるものに対して挙動が異なる 構文: (型)

キャストの例

(int)4.5 4.5 を 4 に切り捨てる (int *)p ポインタの型を変える const 型を非 const 型に変更することもできる

キャストはバグの温床なので多用しない

() はいろいろなところで使われるので検索で見つ けづらい 2014-07-13 C プログラミング入門 総機1 (月1)

8

キャスト

演算子の一種 const を使う 意義がなくな るので、やる べきではない

(9)

C89 まではローカル変数

は必ずブロックの先頭で

宣言する必要がある

C99 以降はどこでも可能

になった

GCC は標準で許容 C++ の文法を導入したもの

使用する直前で宣言する

ほうがコードが読みやす

2014-07-13 C プログラミング入門 総機1 (月1)

9

ローカル変数の宣言位置

{ int i, j, k; // int sum = 0; ... 長いプログラム ... int sum = 0; for(... { sum += s[i]; ... } } ここで定義す るよりは… ここで定義す れば、ここか ら始めて使わ れることがわ かる ここでは sum は全 く使われ ない

(10)

関数の外で宣言される変

宣言位置以降どこでも可視 初期化がない場合、 0 に初 期化される

ソース全体の定数などに

利用

2014-07-13 C プログラミング入門 総機1 (月1)

10

グローバル変数

#include <stdio.h> const int PI = 3.1415; int count; int func1(void) { ... } int main(void) { ... } 実行開始時に 0 に初期化される const を付けて、 定数として使う デフォルトで外部リンケージを持つため、 ほかのプログラムとの共有をしない場合 は static を付ける。詳細略

(11)

関数の変数宣言に static

を付けるとグローバル変

数と同様にプログラムの

開始時から終了まで生存

する変数となる

スコープはその関数のみ 初期化を指定しない場合 0 に初期化される 2014-07-13 C プログラミング入門 総機1 (月1)

11

関数内の static 宣言

#include <stdio.h> int count(void) { static int n = 0; ++n; return n; } int main(void) { printf("%d¥n", count()); printf("%d¥n", count()); ... 書かなくても 0 に初期化される 呼び出すたびに 1 増える グローバル変数に対する static とは効 果が異なる

(12)

再掲

2014-07-13 C プログラミング入門 総機1 (月1)

12

変数とポインタと動的メモリ確保の整理

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

(13)

#

で始まるものは、プログラムのコンパイル

前にプリプロセッサというソフトで処理され

る。これをディレクティブという

#include によるヘッダファイルの読み込みや

#define のマクロなどはこれの一種

#if, #ifdef, #ifndef, #endif, #define,

#undef

, #line などがある

詳細は、リファレンスサイトで調べてください。

2014-07-13 C プログラミング入門 総機1 (月1)

13

(14)

主に定数を書く際に用いられる

通常のマクロと、関数型のマクロがある どちらも #define ディレクティブで定義する

#define MVAL 100 ソースコード中のすべての MVAL を、文字列 100 で置き換える

多くの場合マクロを使わず、グローバル変数

を書くべき

static const int MVAL = 100;

2014-07-13 C プログラミング入門 総機1 (月1)

14

マクロ

最後にセミコロンは付けない 間に = を書かない 関数の外で書く 値の型が必要

(15)

標準ライブラリでは、定数の多くがマクロで

定義されている

RAND_MAX 乱数の最大値 EXIT_SUCCESS, EXIT_FAILURE return の後に 0 や 1 を書く代わりに使う ERANGE 数学関数のエラーコード EOF ファイルの終端 2014-07-13 C プログラミング入門 総機1 (月1)

15

マクロ

(16)

関数型マクロは、関数の様に引数を与えるこ

とができる

特に理由がない限り、普通の関数を使うべき 標準ライブラリ関数のいくつかはマクロである

#define xy2idx(x,y,w) ((x)+(y)*(w)) いつも決まった式を書く場合に便利 2014-07-13 C プログラミング入門 総機1 (月1)

16

関数型マクロ

単純なソースコード上の文字列の置 き換えになるので、解釈がおかしく ならないように、引数それぞれと、 式全体に括弧を付ける

(17)

標準ライブラリの関数型マクロの例

getc(fp) fgetc(fp) と等価

assert(exp) exp が偽であれば異常終了する

2014-07-13 C プログラミング入門 総機1 (月1)

17

(18)

プログラミング技術

(19)

関数の引数がポインタであり、それを通して

値を変更しない場合は常に const を付ける

(説明済み)

ローカル変数で変更をしないものには常に

const を付ける

コンパイラによる最適化(高速化)が期待で

きる

2014-07-13 C プログラミング入門 総機1 (月1)

19

const コレクトネス

(20)

ソースコード中で、

常に成り立つ条件を

コード

で表す

assert マクロを使う 条件を満たさない場合、 異常終了する 常に条件が満たされる ようにコードを書く 2014-07-13 C プログラミング入門 総機1 (月1)

20

アサーション(表明) (assertion)

#include <stdio.h> #include <assert.h> // n 要素の int 配列 a の総和

int sum(const int *a, int n) { int s = 0, i; assert(n > 0); assert(a != NULL); for(i = 0; i < n; ++i) { s += a[i]; } return s; } 条件を満たさない 限り以降の処理が 正しく行われない ので、絶対に進ま せない プログラムのバグがない 全てのアサーションが真 コメントで書くよ り効果的

(21)

条件判断には計算時間がかかるため、リリー

ス製品のような場合には無効化する

NDEBUG マクロを定義すると、条件式が空行に置き 代わる gcc では、コンパイル時に -DNDEBUG オプション を付ける 2014-07-13 C プログラミング入門 総機1 (月1)

21

アサーションの無効化

(22)

バグのないプログラム⇒全てのアサーション

が真

プログラマは、アサーションに違反しないように 関数を呼び出すことを強制される(契約) アサーションは、多ければ多いほど良い 一度書いたアサーションは基本的に消さない

詳細は、以下のキーワードで調べてください

事前条件・事後条件・不変条件 ホーア論理 (Hoare logic)

契約プログラミング (Programming (Design) by Contract) 2014-07-13 C プログラミング入門 総機1 (月1)

22

(23)

リンク (link) コンパイル (compile) 2014-07-13 C プログラミング入門 総機1 (月1)

23

コンパイルとリンク

myprog1.c savePGM() drawLine() • func1() • main() 標準ライブラリ (libc.so) • printf() • malloc() • ... myprog1.o 使用するコンパイラに 付属するライブラリ myprog1 それぞれを行うソフトウェアを、 コンパイラ (compiler), リンカ (linker) という gcc は、これらを総合して実行 するコンパイラドライバである 実行可能形式 (executable) オブジェクトファイル ソースコード ファイル

(24)

いくつかのプログラムで共通の処理を、ソー

スコードから分離する

2014-07-13 C プログラミング入門 総機1 (月1)

24

モジュールプログラミング

myprog1.c savePGM() drawLine() • func1() • main() myprog2.c savePGM() loadPGM() • func2() • main() myprog3.c savePGM() loadPGM() drawLine() • main() 同じ関数が複数のプロ グラムに存在する pgm_module.c savePGM() loadPGM() drawLine() 共通の処理を抜き出す

(25)

2014-07-13 C プログラミング入門 総機1 (月1)

25

モジュールプログラミング

myprog1.c • func1() • main() 標準ライブラリ myprog1.o コンパイル リンク myprog1 pgm_module.c savePGM() loadPGM() drawLine() pmg_module.o モジュール モジュール に分けた関 数は含んで いない

(26)

それぞれのソースをコンパイルして、オブ

ジェクトファイルを生成

 gcc -c -o pgm_module.o pgm_module.c –Wall –Wextra  gcc -c -o myprog1.o myprog.c –Wall –Wextra

リンク

gcc -o myprog1 myprog.o pgm_module.o –Wall –Wextra

2014-07-13 C プログラミング入門 総機1 (月1)

26

(27)

2014-07-13 C プログラミング入門 総機1 (月1)

27

外部リンケージ

myprog1.c static int func1(void); • main() 標準ライブラリ myprog1.o コンパイル リンク myprog1 pgm_module.c savePGM() loadPGM() drawLine() pmg_module.o 公開される関数 • savePGM • loadPGM • drawLine 公開される関数 • main リンクの対象となる公開され た関数やグローバル変数は外 部リンケージを持つという 関数やグローバル変数は普通 は外部リンケージを持つ 他のモジュールから使われる ことのない関数, グローバル 変数には static を付ける 複数のオブジェクトファイルが同じ名 前の関数や変数を公開している場合、 リンクの結果は未定義である。した がって、最小限のものだけを公開する 必要がある

(28)

モジュール分けするために以下のことをする

モジュールで公開しない関数に static を付ける モジュールで公開しないグローバル変数に static を付ける モジュールのヘッダファイルとして、公開する関 数のプロトタイプ、公開するグローバル変数の extern 宣言を書く ヘッダファイルにインクルードガードを書く モジュールで自分のヘッダをインクルードする

詳細は、書籍などを参照

2014-07-13 C プログラミング入門 総機1 (月1)

28

モジュールの作成

参照

関連したドキュメント

日本語で書かれた解説がほとんどないので , 専門用 語の訳出を独自に試みた ( たとえば variety を「多様クラス」と訳したり , subdirect

(出所:総務省 統一的な基準による地方公会計マニュアルに一部追記 平成 27

Angola Cameroon Congo Côte d’Ivoire Equatorial Guinea Gabon. Ghana Nigeria Sierra Leone

データなし データなし データなし データなし

◆第2計画期間末までにグリーンエネルギー証書等 ※1 として発行 ※2

高効率熱源機器の導入(1.1) 高効率照明器具の導入(3.1) 高効率冷却塔の導入(1.2) 高輝度型誘導灯の導入(3.2)

※ 2 既に提出しており、記載内容に変更がない場合は添付不要

排出量取引セミナー に出展したことのある クレジットの販売・仲介を 行っている事業者の情報