Skip to content

Latest commit

 

History

History
632 lines (550 loc) · 18.7 KB

20210911104632-c_language.org

File metadata and controls

632 lines (550 loc) · 18.7 KB

C言語

:header-args+: :wrap :results raw

概要

C言語は汎用のProgramming Language。OS、プログラミング言語、ハードウェアとの接続といった基盤的な部分で使われる。

たとえば。

  • Linux
  • Ruby
  • Python
  • Emacs

現在基盤として使われている多くのプログラムがCで書かれていて、OSSとして公開されている。別の言語で書くにしても、既存の巨大なコード群を参考にできるのは大きな利点。

Memo

ラインエディタedのメイン関数

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

shellのノード定義

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

strlenの実装

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;
}

渡したメモリ位置を更新する関数といえる。

Tasks

Cの詳細な解説本。

Cの解説本。

元のコンセプトはシンプルとのこと。

WEB版の入門書。

  • 41, 59, 67, 103, 105

楽しい入門書。

Reference

C言語のweakシンボルの使い方。

GCの実装の解説。

C言語のチュートリアル。

日本語版。

C++の提案書。

なんだかすごい人。

C++の開発者へのインタビュー。

Archives