|
|
|
| 2008/10/07 11:46||▲
|
|
|
前回に引き続き<stdint.h>についてです。今回は、<stdint.h>内で定義されるマクロに関してお話します。
まずは、intN_t型、uintN_t型、intmax_t型、およびuintmax_t型の定数を作るためのマクロです。実際には、それらの型に完全に合致するわけではなく、それらの型を汎整数拡張した型にするものです。これらのマクロは、C++では、__STDC_CONSTANT_MACROSマクロが定義されている場合のみ定義されるので、
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* 内容 */ #endif
のようにしなければなりません。そして、実際のマクロ定義は、
#define INT8_C(n) (n) #define UINT8_C(n) (n) #define INT16_C(n) (n) #if __INT_MAX__ == 32767 #define UINT16_C(n) (n##U) #else #define UINT16_C(n) (n) #endif #define INT32_C(n) (n##L) #define UINT32_C(n) (n##UL) #define INT64_C(n) (n##LL) #define UINT64_C(n) (n##ULL) #define INTMAX_C(n) (n##LL) #define UINTMAX_C(n) (n##ULL)
のようになります。ここで、UINT16_Cに関しては、int型が16ビットの場合には、unsigned int型にしなければなりませんので、添え字の U を付加しています。
次は、最大最小値に関するマクロです。これらのマクロは、C++では、__STDC_LIMIT_MACROSマクロが定義されている場合のみ定義されるので、
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) /* 内容 */ #endif
のようにしなければなりません。それでは、実際のマクロ定義を見ていきます。<stdint.h>で定義した型に関しては、定義に用いた基本型の最大最小値と同じになるので、<limits.h>のときと同様に、
#define INT8_MAX 127 #define INT8_MIN (-128) #define UINT8_MAX 255 #define INT16_MAX 32767 #define INT16_MIN (-32767-1) #define UINT16_MAX 0xffff #define INT32_MAX __LONG_MAX__ #define INT32_MIN (-__LONG_MAX__-1) #define UINT32_MAX (__LONG_MAX__*2UL+1) #define INT64_MAX __LONG_LONG_MAX__ #define INT64_MIN (__LONG_LONG_MAX__-1) #define UINT64_MAX (__LONG_LONG_MAX__*2ULL+1)
#define INTMAX_MAX __LONG_LONG_MAX__ #define INTMAX_MIN (__LONG_LONG_MAX__-1) #define UINTMAX_MAX (__LONG_LONG_MAX__*2ULL+1)
#if defined(__H8300__) || defined(__NORMAL_MODE__) #define INTPTR_MAX __INT_MAX__ #define INTPTR_MIN (-__INT_MAX__-1) #define UINTPTR_MAX (__INT_MAX*2U+1) #else #define INTPTR_MAX __LONG_MAX__ #define INTPTR_MIN (-__LONG_MAX__-1) #define UINTPTR_MAX (__LONG_MAX*2U+1) #endif
と定義することができます。
<stdint.h>では、他のヘッダで定義される整数型の最大最小値も定義する必要があります。まずは、size_t型の最大値です。<stddef.h>では、size_t型を__SIZE_TYPE__マクロを使って定義しましたが、#if指令で使用できる定数にするためにはキャストが使えないため、ここではsize_t型の実際の型を知る必要があります。そこで、
echo __SIZE_TYPE__ | h8300-hms-gcc -E - [オプション]
といったコマンドを使って、__SIZE_TYPE__の定義内容を調べました。すると、H8/300、およびH8/300HとH8Sのノーマルモードでは、unsigned int型、それ以外(H8/300HとH8Sのアドバンストモード)ではunsigned long型でした。したがって、
#if defined(__H8300__) || defined(__NORMAL_MODE__) #define SIZE_MAX (__INT_MAX__*2U+1) #else #define SIZE_MAX (__LONG_MAX__*2UL+1) #endif
と定義することができます。
次に、ptrdiff_t型の最大最小値ですが、同様の方法で__PTRDIFF_TYPE__の定義内容を調べると、やはり、H8/300、およびH8/300HとH8Sのノーマルモードでは、int型、それ以外ではlong型でした。したがって、
#if defined(__H8300__) || defined(__NORMAL_MODE__) #define PTRDIFF_MAX __INT_MAX__ #define PTRDIFF_MIN (-__INT_MAX__-1) #else #define PTRDIFF_MAX __LONG_MAX__ #define PTRDIFF_MIN (-__LONG_MAX__-1) #endif
のように定義することができます。
次は、wchar_t型の最大最小値ですが、やはり同様に__WCHAR_MAX__の定義内容を調べると、オプションに関わらずunsigned short型でしたので、
#define WCHAR_MAX 0xffff #if __INT_MAX__ == 32767 #define WCHAR_MIN 0U #else #define WCHAR_MIN 0 #endif
のように定義することができます。WCHAR_MINは、int型が16ビットの場合はunsigned int型に、32ビットの場合はint型に評価されなければならないため、上記のようにしています。
最後が、sig_atomic_t型の最大最小値です。sig_atomic_t型は、その型のオブジェクトに対する読み書きがアトミックオペレーションで行われなければなりません。これはプロセッサの命令セットに依存します。
H8/300の場合、汎用レジスタのサイズは16ビットなので、sig_atomic_t型も16ビット以下でなければなりません。H8/300HおよびH8Sは汎用レジスタのサイズが32ビットありますので、32ビット以下の型にすることができます。したがって、H8/300では、sig_atomic_t型をshort型に、それ以外はint型に定義することにしました。したがって、
#ifdef __H8300__ #define SIG_ATOMIC_MAX 32767 #define SIG_ATOMIC_MIN (-32767-1) #else #define SIG_ATOMIC_MAX __INT_MAX__ #define SIG_ATOMIC_MIN (-__INT_MAX__-1) #endif
と定義することができます。
これで<stdint.h>の実装も終わりです。そしてこれにより、C99に対応した、フリースタンディング環境で必要とされる全ライブラリの実装が終わったことになります。次回からは、ホスト環境互換のライブラリに手を付けていきます。
|
| 2006/01/27 01:46|処理系の特性|TB:0|CM:0|▲
|
|
|
コメント
|
|
コメントの投稿
|
|
|
|
|
トラックバック
|
トラックバックURLはこちら
http://libc.blog47.fc2.com/tb.php/16-3330cb34
|
|
|
|
|
ホーム
全記事一覧
<< 前の記事
次の記事 >>
|