試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

GLib 2が用意している基本的なデータ型について(ページ2/3)

GLib 2が用意している基本的なデータ型について(ページ1/3)」の続き。

環境によらずbit数/値の範囲を保証する型

GLibが提供する型の中にはbit数を保証する型が存在し、例えばgint64という型はどのアーキテクチャであっても64bitであることが保証される(扱える値の範囲もこれに対応して決まる)。こういった型の定義はGLibの中のアーキテクチャ依存なヘッダファイル/usr/lib(64)/glib-2.0/include/glibconfig.hの中に記述されており、自動的に参照される(手動で取り込んだりする必要はない)。

GLibの用意する型の内、bit数が保証されているもの
型の説明GLibが用意する型 (範囲)
整数型/符号あり/8bitgint8 (G_MININT8 - G_MAXINT8)
整数型/符号なし/8bit (バイト単位の処理に使える)guint8 (0 - G_MAXUINT8)
整数型/符号あり/16bitgint16 (G_MININT16 - G_MAXINT16)
整数型/符号なし/16bitguint16 (0 - G_MAXUINT16)
整数型/符号あり/32bitgint32 (G_MININT32 - G_MAXINT32)
整数型/符号なし/32bitguint32 (0 - G_MAXUINT32)
整数型/符号あり/64bitgint64 (G_MININT64 - G_MAXINT64)
整数型/符号なし/64bitguint64 (0 - G_MAXUINT64)
バイト(8bit)単位で処理を行う際の型(範囲0 - 255)としてはguint8もしくはgucharの型が適する。
一般的には1バイトに相当するbit数(アルファベットや数字の1文字のコードを表現するのに必要なbit数でlimits.hのCHAR_BITの値)というものは仕様では決まっていないようだが、2010年現在主流となっているPCのアーキテクチャでは1byte=8bitとなっている。
例として、GLibのByte Arrays(日本語訳)という機能もバイト単位のデータはguint8型を用いており、GIOのg_data_output_stream_put_byte()関数ではguchar型を用いている。

printf()系関数のフォーマット文字列指定

bit数の保証されている型をprintf()系関数で扱う場合には、そのフォーマット文字列(printf()の場合は1番目の引数)の「%」の後ろの部分が「G_[型名]_FORMAT」というマクロになっているのでこれを用いる(こうしないと適当に書いた指定で偶然それが動いたとしても環境依存なコードとなってしまう)。

gint64 i = G_MAXINT64;
printf ("i = %" G_GINT64_FORMAT "\n", i);

上はgint64型の例だが、guint64型では「G_GUINT64_FORMAT」のように「U」が付く。
具体例なマクロは
http://web.archive.org/web/20080609054222/www.gnome.gr.jp/docs/glib-2.8.x-refs/glib/glib-Miscellaneous-Macros.html
にある。

関連:GLibに動的リンク(実行時に依存)せずにbit数保証の型のみを用いる

GLibを用いて作成したプログラムは実行時にGLibの共有オブジェクトに動的リンクすることになるが、本記事で扱っているような型の定義についてはヘッダファイルの中で完結しているものなので(共有オブジェクトから取り出す必要がない)、上記のようなbit数の保証されるデータ型は欲しいが実行時にGLibに依存したくないという場合でも

  • GLibの開発パッケージをインストールする
  • 「#include 」をC言語のソースの最初の辺りに記述する
  • コンパイル時にコマンド行の中に「$(pkg-config --cflags glib-2.0)」をオプションとして含める

という手順のみでこうした型を利用しつつ実行時にGLibに依存しない実行ファイルが作成できる。
下は例。
[任意]ファイル名: gint64test.c

/*
 * GLibに実行時に依存せずにbit数の保証される型を用いる(GLibの開発パッケージは必要)
 * 注意点としては、GLibの関数を用いないようにする
 *
 * gcc -O2 -Wall -Wextra $(pkg-config --cflags glib-2.0) gint64test.c -o gint64test
 */

#include <stdlib.h>
#include <stdio.h>
#include <glib.h>

int
main ()
{
  gint64 i = G_MAXINT64;
  printf ("i = %" G_GINT64_FORMAT "\n", i);
  return EXIT_SUCCESS;
}

実行結果はアーキテクチャによらず下のようになる。

i = 9223372036854775807

これはCライブラリのみに依存する実行ファイルとなる。

$ objdump -p [gint64testの場所] | grep NEEDED
  NEEDED               libc.so.6

(「GLib 2が用意している基本的なデータ型について(ページ3/3)」に続く)

関連記事:

参考URL: