2007-04-01から1ヶ月間の記事一覧

ハッシュ法

ハッシュ法とは、文字列を整数に写像する処理のことをいう。ハッシュ関数は文字列またはデータ構造をを有界の整数(hash bucket)に写像する。ハッシュ法を使ったどんなアル ゴリズムも、衝突が起こることを考慮にいれなければならない。

文字定数の型

C

Cの文字定数はint型を持つ。よって、例えばsizeof('a')はsizeof(int)と同値である。sizeof(char)の値とはならない。

5["abcdef"]という式が文法上正しい理由

C

aをポインタ、eを整数とする。a[e]は*(a+e)のシンタックスシュガーであり、また*(a+e)と*(e+a)は等価であるから、a[e]はe[a]と書いても同じ意味となる。 また、文字列リテラルを表す"abcdef"は文字列の先頭アドレスと解釈される。従って、"abcdef"[5]という…

入力バッファに読まれていない入力を捨てる方法

一般的な解法は無い。例えばfflush()は、出力ストリームにしか定義されていないので、fflush(stdin)は効かないと考えるべき。以下のようにラッパーを作成する方法が考えられる。 char *xfgets(char *s, size_t n, FILE *f) { char *p; int c; if (!fgets(s, …

static変数の初期値

C

関数の外で宣言した変数や記憶域クラスをstaticと宣言した変数は、「=0」と打ち込んだかのように、0に(プログラムの立ち上がり時に一度だけ)初期化されることが保証されている。ポインターはNULLポインターに、浮動小数は0.0に初期化される。

疑似乱数

C

0以上1以下の乱数を生成するコード。括弧の位置に注意。 random_number = (1.0 / RAND_MAX) * rand(); 0以上2未満なら以下となる。RAND_MAXへは1.0を足す(単純に1だと整数のオーバーフロとなる) random_number = (2.0 / (RAND_MAX + 1.0)) * rand();

代替関数の例

gets → fgets sprintf → snprintf strcat → strncat strcpy → strncpy vsprintf → vsnprintf

バッファオーバーラン対策

IPA セキュア・プログラミング講座より。 http://www.ipa.go.jp/security/awareness/vendor/programming/intro.html 少し几帳面になるだけで簡単にバッファオーバーラン攻撃を防ぐことができる。プログラムを作成するときに次のたった1つの質問を自分自身に…

コメントの指針

関数を定義する場合には、それが何をする関数で、どのような場合にどんな値を戻すのかを書く。 変数に対するコメントは、その値がどのような場合に、どういう意味を持っているのかを書く。 繰り返し処理(for, whileなど)に対しては、どのような条件で繰り返…

PROXY

/etc/profile.d/ に在るスクリプトはログイン時に実行されるので以下のようなスクリプトを作成して置いておくとPROXYの設定が出来て少し嬉しい。proxy.sh export http_proxy=http://proxy.example.com:port/ export ftp_proxy=http://proxy.example.com:port…

記憶管理 malloc() & free()

C

free()で解放した後にその領域を使うのはエラーである。以下が良くある間違いの例 /* free()で解放しているのでp->nextの参照は間違い */ for (p = head; p != NULL; p = p->next) free(p); 正しい方法 for (p = head; p != NULL; p = q) { q = p->next; fre…

returnとexitの違い

C

return その関数を終了し、その関数の呼び出し元へ処理を戻す。 exit() 関数。プロセスを終了し、そのプロセス呼び出し元(OS)へ処理を戻す。

可変引数リスト

C

宣言"..."は、引数の個数と型が可変であることを示す。 int printf(char *fmt, ...) 可変引数の取り扱いは man3(stdarg)及びK&R P.190を参照せよ

型の範囲をプリントする

C

#include #include #include int main(void) { printf("int =%d〜%d\n",INT_MIN,INT_MAX); printf("short int =%d〜%d\n",SHRT_MIN,SHRT_MAX); printf("unsigned short int =%u\n",USHRT_MAX); printf("unsigned int =%u\n",UINT_MAX); printf("long int =%l…

連結リストをたどる場合の慣用句

for (ptr = head; ptr != NULL; ptr = ptr->next) { ... } または for (ptr = head; ptr != NULL; ptr = ptr->next) { ... } 状況によって使い分ける。

ビット演算

C

#define KEYWORD 01 #define EXTERNAL 02 #define STATIC 04 flags |= EXTERNAL | STATIC; /* EXTERNAL | STATIC が先に評価され、flags とのorが評価される。 * a = b = c = 0 が右から評価されるのと同じ。 */ flags &= ~(EXTERNAL | STATIC); /* いずれの…

複雑な宣言

C

殆どパズル。図を書いていくと理解しやすいと思う。 例1 char (*(*x())[])() xは関数であり、その戻り値はポインタである。 そのポインタはあるポインタ配列の先頭を指し示す。 あるポインタ配列の各ポインタは、char型を返す関数を指し示す。 つまり、xはch…

関数ポインタ

C

以下のように宣言する関数が有るとする。第4引数が関数ポインタである。 void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *) ); この関数は、例えば以下のように使用する。 qsort( (void **) lineptr, 0, nlines-1, (int (*)(vo…

単純なgrepコマンド

C

単純なgrep。引数で与えられた文字列にHITすると印字する。ただし-xオプションが与えられていれば逆に印字しない。また-nオプションでHITした行番号も印字する。オプションは-nxの書式も許可する。 以下はK&Rから。ただし分かりづらかったのでwhile文はfor文…

コマンド行の引数

C

mainが呼び出された時、二つの引数(argc, argv)が渡される。 int argc コマンド行の引数の個数 char *argv[] argvはchar型のポインタ配列へのポインタである ポインタ配列の最後は標準規格により、NULLである ポインタ配列の宣言の理解 "char *argv[]"という…

Xでのキーコードの調べ方

xevコマンドを使う。xevは X のイベントを表示する。起動するとウィンドウが表示され、そのウィンドウに渡されるイベントが表示される。ウィンドウ上でキーを叩くとキーコードが分かる。大抵xmodmap設定時に使うらしい。 ESCキーを叩いた時の例。keycodeは9…

キーマップの変更

Fedora Core6での自分好みのキーマップ変更方法。 1. Caps LockキーもCtrlにする システム -> キーボードから「キーボードの設定」を開き、「レイアウトのオプション」タブから「Ctrl key position」-> Make CapsLock an addtional Ctrl.」を選択すると目的…

宣言

C

以下の宣言は全て意味が異なる。 char num = 0 ; char num_chr = '0'; char num_str[] = "0"; char *num_ptr = "0";

sortの骨子

C

K&Rより。sortコマンドの骨子となるプログラム。存外単純な内容だが、なかなか示唆に富んでいるので残すことにする。各処理は極力標準ライブラリに置き換えた。分割コンパイルの実験も兼ねたので必要以上細分化してある。 ソース sort.h readlines.c getline…

ポインタ対多次元配列

C

以下の宣言を考える。 int a[10][20]; int *b[10]; 多次元配列 aは真の配列であり、200個のintサイズの記憶場所が割り付けられる ポインタ配列 10個のポインタが割り付けられるだけであり、初期化は行われない 配列の列は異なる長さでも良い(これが重要な利…

ポインタ配列の初期化

C

n番目の月の名前の文字列へのポインタを返す関数。内部的なstatic配列の理想的な応用例、らしい。関数内のstatic宣言は、恒久的な変数になるから、関数外部からアクセスされるこれらの文字列をstaticで宣言する、ということで理解した。しかしながら、static…

makeを使った分割コンパイルにチャレンジ

……しているのだがうまくいかない。今日は流石にタイムアウト。

文字列のコピーは以下のように書ける。

C

/* strcpy1 */ void strcpy(char *s, char t) { while ((*s = *t) != '\0') { s++; t++; } } これは以下のように簡略化できる。 /* strcpy2 */ void strcpy(char *s, char t) { while ((*s++ = *t++) != '\0') { ; } } これはさらに以下のように簡略化できる…

配列とポインタ

C

次の定義には重要な差がある。 char array_message[] = "now is the time"; char *ptr_message = "now is the time"; 配列の中の文字は変わり得るが、array_messageは常に同じメモリ位置を指す。 ptr_messageは文字列リテラルを指すポインタである。文字列リ…

ポインタと配列

寝付きが悪いのでもう少し。配列名とポインタの間の以下の違いは心にとどめておく必要がある。(K&R P.121) ポインタは変数であり、従って以下の演算には意味がある pa = a pa++ 配列は変数ではない為、上記の構文は正しくない。 配列名が関数に渡される時、…