tak0kadaの何でもノート

発声練習、生存確認用。

医学関連は 医学ノート

「Cの絵本」第5章~第8章、付録を読んだ

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..が自動的に指定される
  • ビット演算
    • 論理積(and &): ビットが両方1なら1それ以外は0
    • 論理和(or |): ビットの少なくとも一方が1なら1それ以外は0
    • 排他的論理和(xor ^): ビットの片方が1でもう片方が0なら1それ以外は0
    • 補数(not~): ビットの反転
    • シフト演算子
      • 右シフト(>>): 右のビットを削除して先頭に0を補充する: a >> 2
      • 左シフト(<<): 左のビットを削除して末尾に0を補充する