The Man Who Fell From The Wrong Side Of The Sky:2007年1月18日分

[最新版] [一覧] [前月] [今月] [翌月]

2007/1/18(Thu)

どのようにしてlibcは後方互換を保つのか?(その1)

国際標準規格(ISO)としてのCは現在のところ

と3つのバージョンが存在します、これらはすべて後方互換が保障されています。

ソースレベルでの後方互換とは

ということに尽きるのですが、ここでひとつ問題が発生します。それは名前の衝突です。

C90:AMD1やC99の改正ではいくつかの新しい標準関数が追加されました。
代表的なものは

$ man 3 mbrtowc
...
STANDARDS
     The mbrtowc() function conforms to ISO/IEC 9899/AMD1:1995 (``ISO C90,
     Amendment 1'').  The restrict qualifier is added at ISO/IEC 9899:1999
     (``ISO C99'').
$ man 3 atoll
STANDARDS
     The atoll() function conforms to ISO/IEC 9899:1999 (``ISO C99'').

などです。

しかしCにはC++のような名前空間はないですし、標準関数の命名規則やユーザ定義関数名の制限
(例えば"stdc_"ではじまる名前は標準関数に予約しユーザには使用を禁ずるなど)もありません。
つまりmbrtowcやatollという関数名はすでにユーザが別の目的に使っていたかもしれないのです。

以下は簡単なサンプルです。

test.c
--
#include <stdio.h>
#include <stdlib.h>

void
atoll(void)
{
	printf("hello, world.\n");
}

int
main(void)
{
	atoll();
	return 0;
}

atollという関数名はC90の頃は自由に使っていい名前だったはずなのに
FedoraCore6(glibc-2.5 + gcc-4.1.1)ではコンパイルに失敗します。

gcc -o test test.c
test.c:5: error: conflicting types for 'atoll'
/usr/include/stdlib.h:159: error: previous declaration of 'atoll' was here

このままではソース互換とはいえません。

この衝突を防ぐため提供される機能が事前定義マクロ__STDC_VERSION__です。
事前定義マクロというのは、何かヘッダをインクルードせずとも予め定義されるマクロです。

__名前__

のように前後にアンダースコアが2つつきます。
規約にはISO Cのバージョン情報として、以下の事前定義マクロあります。

#define __STDC__		1		/* ISO-Cである		*/
#undef __STDC_VERSION__				/* C90では定義されない	*/
#define __STDC_VERSION__	199409L		/* C90:AMD1の場合	*/
#define __STDC_VERSION__	199901L		/* C99の場合		*/

この値をセットするのはプリプロセッサです。
gccの場合-stdオプションを使うことで__STDC_VERSION__を制御できます。

などの名前空間保護もあるのですが、手法は同じなので解説を割愛させていただきます。

次回はバイナリレベルでの後方互換性の話です。

NetBSD

今回なぜFC6使って解説してるかというと...それはNetBSDが(ry

めも

B-Treeでなくskip listsアルゴリズムを使ったDBM、 SkipDB。sleepycat BDB4やqdbmより速いらしい。
ライセンスは3-clause BSDL、そのうち試してみよ。


[ホームへ] [ページトップへ]