「C言語」の版間の差分
提供: Wikinote
(→マクロ) |
(→覚え書き) |
||
| 行2: | 行2: | ||
== 覚え書き == | == 覚え書き == | ||
| + | === 関数ポインタ === | ||
| + | いつまでたっても覚えられない。使わないからなあ…。 | ||
| + | int (*func)(int x); // int を引き数にとり、int を返す関数へのポインタ | ||
| + | |||
=== <code>printf</code> のフォーマット === | === <code>printf</code> のフォーマット === | ||
* [http://www.linux.or.jp/JM/html/LDP_man-pages/man3/printf.3.html Manpage of PRINTF] | * [http://www.linux.or.jp/JM/html/LDP_man-pages/man3/printf.3.html Manpage of PRINTF] | ||
2009年2月5日 (木) 23:34時点における版
C 言語 最高 再考。
目次
覚え書き
関数ポインタ
いつまでたっても覚えられない。使わないからなあ…。
int (*func)(int x); // int を引き数にとり、int を返す関数へのポインタ
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] = {};