C言語は汎用のProgramming Language。OS、プログラミング言語、ハードウェアとの接続といった基盤的な部分で使われる。
たとえば。
- Linux
- Ruby
- Python
- Emacs
現在基盤として使われている多くのプログラムがCで書かれていて、OSSとして公開されている。別の言語で書くにしても、既存の巨大なコード群を参考にできるのは大きな利点。
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/bin/ed/main.c#L113
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/games/arithmetic/arithmetic.c#L156-L162
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/bin/sh/nodetypes#L56-L61
バイナリツリーの中にはleft, rightを持つものがあり、leftは小さい、rightは大きいとしてノードの順番を決定する。
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/external/bsd/libbind/dist/include/isc/tree.h#L44-L49
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/external/bsd/libbind/dist/isc/tree.c#L105-L130
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/external/bsd/libbind/dist/isc/tree.c#L155-L169
- ツリーは言語構造の表現ができる
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/usr.bin/xlint/lint1/lint1.h#L284-L305
シンボルテーブルの構築によく使われる。
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/games/battlestar/parse.c#L75-L84
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/bin/csh/lex.c#L176-L189
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/usr.bin/rup/rup.c#L63-L70
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/usr.bin/rup/rup.c#L79-L105
nextという要素を持つ構造体は1方向リスト連結リストのノードを定義する。
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/usr.bin/rup/rup.c#L108-L134
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/usr.bin/telnet/commands.c#L1700-L1716
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/lib/libc/time/localtime.c#L869-L871
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/lib/libc/time/localtime.c#L864-L867
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/external/bsd/file/dist/src/tar.h#L53-L71
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/include/rpc/rpc_msg.h#L54-L57
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/include/rpc/rpc_msg.h#L149-L155
共用体はメモリを共用し、節約するために用いる。
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/lib/libbsdmalloc/malloc.c#L75-L89
空き状態と専有状態を同時にとることはないので、同じメモリ空間を共用できる。
外部媒体のデータ構造を表現するために構造体が用いられる。
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/sys/dev/ic/i82557reg.h#L147-L151
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/external/bsd/tcpdump/dist/tcp.h#L37-L47
https://github.com/kd-collective/NetBSD/blob/89341ae2e1875e7f91cefa9b1dcc0e4549edcde0/common/lib/libc/string/strlen.c#L49-L56
ポインタを文字列の終端に達するまでインクリメントして、先頭のアドレスを差し引く。
#include <stdio.h>
#include <string.h>
int test_strlen(char *str) // strは先頭のアドレス
{
char *s;
for (s = str; *s; ++s)
continue; // 要素の数だけインクリメント
return(s - str); // 進んだ分を求める
}
無限ループの書き方。条件を指定しない。
https://github.com/kd-collective/emacs/blob/d983e080e027bd7b680b1e40ccfa0c71d6a3cd94/lib-src/emacsclient.c#L275-L286
配列変数には先頭の要素へのポインタが入っていて、インデックスをその分ずらすことで要素を取得できる。配列が0から始まるのはそのため。
- 最初の要素は、*doses もしくは doses[0] で取得できる。
doses[3] == *(doses + 3) == *(3 + doses) == 3[doses]
void skip(char *msg)
{
puts(msg + 6);
}
char *msg_from_amy = "Dont call me";
skip(msg_from_amy);
関数呼び出しのとき、デフォルトは値渡しで、コピーされた値が使用される。コピーされるので、呼び出し元の引数の値は変化しない。変化させたいときは、参照を渡す必要がある。
void move(int *lat, int *lon) {
*lat = *lat + 1; // 引数で渡されたlatにはメモリアドレスが入っているので、格納している値を読み込むために*を使う。
*lon = *lon + 1;
}
int main() {
int latitude = 32;
int longitude = 64;
move(&latitude, &longitude); // 参照を渡す。参照でない場合、単なる値のコピーとなって、move()内で全く関係ないローカル変数の値が変わるだけになる。main()内の値は変わらない。
printf("停止...現在位置:[%i, %i]\n", latitude, longitude);
return 0;
}
渡したメモリ位置を更新する関数といえる。
Cの詳細な解説本。
Cの解説本。
元のコンセプトはシンプルとのこと。
WEB版の入門書。
- 41, 59, 67, 103, 105
楽しい入門書。
C言語のweakシンボルの使い方。
GCの実装の解説。
C言語のチュートリアル。
日本語版。
C++の提案書。
なんだかすごい人。
C++の開発者へのインタビュー。