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

プロフィール 

Author:高木信尚

ホームページ
ブログ

最近の記事 

最近のコメント 

最近のトラックバック 

月別アーカイブ 

カテゴリー 

ブロとも申請フォーム 

この人とブロともになる

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

 

2008/10/07 11:49|

 

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フィード 

リンク 

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

Powered By FC2ブログ 

Powered By FC2ブログ
ブログやるならFC2ブログ

Copyright(C) 2006 TAKAGI Nobuhisa All rights reserved.
Powered by FC2ブログ. 無料ホームページ アフィリエイト レンタルサーバー FC2ブログ 一戸建て template designed by 遥かなるわらしべ長者への挑戦.