http://takuyaokada.hatenablog.com/entry/20150522/1432221634の続き。
5章: 関数
- スコープ
float pi = 3.14; void func() { char s = "abc"; } main() { printf(pi); // ok printf(s); // error }
- プロトタイプ: 方だけを先に定義
# include <...> int addnum(int, int); main() {} int addnum {}; /* 下は駄目な例 */ # include <...> main(){ int x = addnum(3, 4); // error; 関数呼び出しより先に定義すること } int addnum(){}
- コマンドライン引数の取得
argc
: 配列argvの大きさ(引数+1)argv[0]
: プログラムファイルのパスの文字列へのポインタargv[1]
: 1番目の引数
6章: ファイルの入出力
- テキストファイル
読み込み
FILE* fp; // 失敗した時はNULLポインタが返ることに注意 // rがreadonly, wがwrite, aがappend fp = fopen("file.txt, "r"); char s[10]; fgets(s, 9, fp); fclose(fp);
feof(fp)
はEOFで真となるのでループで処理するのに使える。
書き込み
if (!(fp = fopen("file.txt", "w"))) return; fputs("hello\n", fp); // 文字列の書き出し fprintf(fp, "%02d\n", 453); // printfと同じ、引数の順番... fclose(fp);
- バイナリファイル
読み込み: r,w,aに加えてb
を追加指定子て開く
short buf[3]; FILE* fp; fp = fopen("file.dat", "rb"); fread(buf, sizeof(short), 3, fp); fclose(fp);
書き込み
fwrite(buf, sizeof(short), 3, fp);
- 標準入出力: stdin、stdout、stderrは標準入出力のためのファイルポインタ
// 同じ printf("hello"); fprintf(stdout, %s, "hello"); /* キーボード入力 */ int a; char s; scanf("%d %s", &a, s); // 指定の書式に変換して格納、格納先はアドレスで指定 char s[10]; gets(s); // 1行分の文字列を文字配列に格納 int c; c = getchar(); // 1文字だけ格納
- ファイルポインタの移動
シークモードはSEEK_SET`でファイルの先頭、
SEEK_CURで現在位置、
SEEK_END``ファイルの最後を指定できる。改行コードが環境によって違うことに注意。
fseek(fp, 移動するバイト数, シークモード);
7章: 構造体
// テンプレートを宣言 struct point_2d { int x; int y; }; // セミコロン忘れやすい // 変数の宣言 struct data{ ... } s; //テンプレートとまとめて変数を宣言 struct point_2d s2; struct point_2d *sp = &s; // 構造体へのポインタ struct point_2d list[4]; // 構造体の配列(テンプレートと同時に指定することも出来る)
アクセス
main() { s.x = 10; s.y = 1; /* アロー演算子でアクセス出来る */ sp->x = 10; sp->y = 1; }
- 型の定義
typedef unsigned char u_char; typedef struct hoge{ ... } foo;
8章: プログラムの構成
- ヘッダファイル: ひたすら定義を書く
includeの仕方
# include "myheader.h"
- コンパイルとリンク
外部変数の定義
// global.h extern double x; // main.c func() { x = 1.0; }
static: staticを付けてグローバル変数を定義すると、有効範囲がそのファイル内に制限される
const: 変数の定義では定数の宣言、関数の引数だと副作用がないことを保証する
- マクロ: #から始まる行
#define PI = 3.14 #define DEBUG_MODE /* 重複インクルード防止 */ #if #endif #ifdef #elsif #else #endif #ifndef #endif /* 引数付きマクロ */ #define FOO(x, y, z) ((x) * (y) * (z) \ - (x) - (y) - (z)) #define BOO(x, y, z) ((x) * (y) * (z) \ - x - y - z) // 上と違う FOO(1,2,3+1) // 1 BOO(1,2,3+1) // 3
付録
- 共用体: 同じアドレスに異なるデータを割り当てる
union unidata { int no; char name[10]; }uni; uni.no = 1; uni.name = "fhaosdhf" // この段階でuni.noの値は保証されない
- enum: 整数値に名前を与える
enum _month{ January, February,.. } month; // Jan=0, Feb=1..が自動的に指定される