C言語

提供: Wikinote
2009年2月4日 (水) 09:45時点におけるHagio (トーク | 投稿記録)による版 (マクロ)

移動: 案内検索

C 言語 最高 再考。

覚え書き

printf のフォーマット

% で始まり、変換指定子で終わる。以下のプログラムで実験。

#include <stdio.h>

int main(void) {
    float f;

    printf("1234567890 1234567890\n");
    printf("---------------------\n");
    f = 123.456;
    printf("%f %f\n", f, -f);               // デフォルト
    printf("%.2f %.2f\n", f, -f);           // 小数点以下桁 (精度) 指定
    printf("%10f %10f\n", f, -f);           // 最小幅指定
    printf("%10.2f %10.2f\n", f, -f);
    printf("%010.2f %010.2f\n", f, -f);     // 0 で埋める
    printf("%-10.2f %-10.2f\n", f, -f);     // 左揃え
    printf("%+10.2f %+10.2f\n", f, -f);     // 必ず符号をつける
    printf("%*.2f %*.2f\n", 15, f, 15, -f); // 引数による幅指定
    printf("%*3$.2f %*3$.2f\n", f, -f, 20); // 引数による幅指定 (引数指定)
    printf("%.*3$f %.*3$f\n", f, -f, 10);   // 引数による精度指定 (引数指定)

    return 0;
}

実行結果は下記のようになる。

$ gcc -o printf printf.c; ./printf
1234567890 1234567890
---------------------
123.456001 -123.456001
123.46 -123.46
123.456001 -123.456001
    123.46    -123.46
0000123.46 -000123.46
123.46     -123.46   
   +123.46    -123.46
         123.46         -123.46
              123.46              -123.46
123.4560012817 -123.4560012817

定数

定数の型
long 123456789L
unsigned 123U
unsigned long 123456789UL
double 123.456
unsigned double 123.456L
float 123.456F
8 進数 0123
16 進数 0x335F
16 進数 unsigned long 0x12ABUL
文字定数 'a'
8 進数ビットパターン '\013'
16 進数ビットパターン '\x1A'
文字列定数 "hello, world"

※大文字、小文字の区別はない。(U, L, X はそれぞれ u, l, x でも同じ。)

  • 列挙定数 (enum) の初期値は 0。
  • 文字列定数はコンパイル時に連結できるので、以下のような書き方も可能である。長い文章を出力するときなどに便利。OSS のソースを見ても、\ で折り返してるケースが多いが、こちらの方がインデントなどなにかと使いやすいように思える。
printf("aaaaaaaaaaaaaaa"
       "bbbbbbbbbbbbbbb"
       "ccccccccccccccc\n");
// print "aaaaaaaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccc\n"

マクロ

引数付きマクロ
#define max(A, B) ((A) > (B) ? (A) : (B))
#define square(x) (x) * (x) // 括弧が重要: square(z+1) を考えよ!

ただし、以下のような使い方はできないことに注意すること。

max(i++, j++); // 大きな方が 2 度インクリメントされる
引用符付き文字列展開 (#)
#define debug_print(var) printf(#var " = %g\n", var)

これは、以下のように展開される。

debug_print(x);
⇒ printf("x" " = %g\n", x);
⇒ printf("x = %g\n", x);    // 文字列は連結される。
実引数連結 (##)
#define joint(prefix, suffix) prefix ## suffix

これは、以下のように展開される。

joint(hoge, 3)
⇒ hoge3

その他 (細かいこと)

  • #define 行の末尾にはセミコロンはいらない
  • extern宣言であって、定義ではない。つまり、領域の確保などは行われない。別ファイルで定義される変数などを利用する際に使う。疑問:ヘッダファイル中で extern 宣言した場合、定義するファイルからそのヘッダを include してもよいのか。⇒ よい (少なくとも、エラーや警告は出ない。)

テクニック

下位 8 ビットマスク

~ (1 の補数) やシフト演算子をうまく使うことで、ビット処理を行う。

x = x & ~0xFF;

配列の初期化

K&R には、以下の記述がある。

配列の初期値式が指定された数より少ないときには、外部変数、静的変数、自動変数については、残りの要素は 0 となる。

つまり、大きな配列を 0 で初期化したい場合、自動変数であっても以下のようにできるということである。

int bigarray[10000] = {0};

ほんとか!? ⇒ ほんと。次のように、要素数 0 での初期化も可能であった。

int bigarray[10000] = {};