fc2ブログ

C99に対応した標準Cライブラリの実装レポートを行っていきます。

プロフィール 

高木信尚

Author:高木信尚

ホームページ
ブログ

最近の記事 

最近のコメント 

最近のトラックバック 

月別アーカイブ 

カテゴリー 

ブロとも申請フォーム 

この人とブロともになる

ホーム 全記事一覧 << 前の記事 次の記事 >>

 

abs関数は、整数の絶対値を求める関数で、int型用がabs、long型用がlabs、long long型用がllabsという名前になります。浮動小数点数用のものは<math.h>ヘッダで、複素数用のものは<complex.h>ヘッダでそれぞれ宣言されますので、ここで扱うのは整数用のものだけです。

実装はいたって簡単で、次のようになります。

int abs(int j)
{
  return j < 0 ? -j : j;
}

labsおよびllabs関数も同様に実装することができますので、ここでは割愛します。この関数は非常に単純ですので、<stdlib.h>ヘッダ内でインライン関数として定義しておき、ユーザーが自分で関数原型を書いて呼び出したときのためだけに、外部定義も用意しておくことにします。

念のため、インライン関数の定義も挙げておきます。

static inline int abs(int __j)
{
  return __j < 0 ? -__j : __j;
}

jを予約済み識別子である__jに変更する以外は、特にこれといった違いはありません。

ところで、このabs関数ですが、引数がINT_MINの場合には、結果もINT_MINになってしまいます。標準規格では、結果が表現できない場合の動作は未定義なので、これでも問題ないのですが、ときどき罠にはまるので注意が必要です。

参考までに、今回は条件演算子を使ってあっさり実装しましたが、RISCのように分岐のコストが大きいプロセッサでは、次のように実装することがあります。

int t = j >> (sizeof(j)*CHAR_BIT-1);
return (j ^ t) - t;

確かにこれで分岐はなくなります。H8の場合には、シフト演算のコストが分岐以上に大きいので、こうした実装は最適とはいえません。



C++のabs関数は、int型だけでなく、long型、float型、double型、long double型それぞれについて多重定義されています。long long型は標準C++ではサポートされないのですが、GCCではサポートされるので、long long型についても多重定義しておいた方がよいでしょう。

#ifdef __cplusplus
inline long abs(long __j) { return __j < 0 ? -__j : __j; }
inline long long abs(long long __j) { return __j < 0 ? -__j : __j; }
inline float abs(float __x) { return __x < 0 ? -__x : __x; }
inline double abs(double __x) { return __x < 0 ? -__x : __x; }
inline long double abs(long double __x) { return __x < 0 ? -__x : __x; }
#endif

他の型のものを勝手に定義してしまうわけにはいかないので、テンプレートは使わず、多重定義によって実装する必要があります。
スポンサーサイト



2006/05/24 00:19|一般ユーティリティTB:0CM:0

コメント
コメントの投稿

管理者にだけ表示を許可する


トラックバック
トラックバックURLはこちら
http://libc.blog47.fc2.com/tb.php/57-0a266884

ホーム 全記事一覧 << 前の記事 次の記事 >>

ブログ内検索 

お勧め書籍 

RSSフィード 

リンク 

このブログをリンクに追加する

Copyright(C) 2006 TAKAGI Nobuhisa All rights reserved.
Powered by FC2ブログ. template designed by 遥かなるわらしべ長者への挑戦.