その他の OS 独立関数

int abs( int num );   (stdlib.h)
long
labs( long num );

絶対値を返します。

参照   fabs

div_t div( int dividend, int divisor );   (stdlib.h)
ldiv_t
ldiv( long dividend, long divisor );

dividenddivisor で割り、商と剰余を返します。結果は次の構造体で返されます。
typedef struct {
  int quot; // 商
  int rem; // 剰余
} div_t;
typedef struct |
  long quot; // 商
  long rem; // 剰余
} ldiv_t;

参照   fmod

void qsort( void* base, size_t num, size_t size, int (*cmp)(void*, void*) ); (stdlib.h)

クイック ソートのアルゴリズムで配列要素を並べ替えます。サイズ size の要素が num 個並んだ配列 base を、関数 cmp の判定に従って並べ替えます。

関数 cmp は、並べ替えの最中に繰り返し呼び出されます。2 つの引数には、配列 base の要素へのポインタが渡されます。関数 cmp からは、第 1 引数の要素が第 2 引数の要素より小さい場合には負の値を、等しい場合は 0 を、大きい場合は正の値を返す必要があります。要素の大小関係は、関数 cmp の実装で自由に決定できます。

次の例では、標準ライブラリ関数 strcmp を使用して、都市名の配列を並べ替えています。
char city[][12] = {
  "Tokyo",
  "Osaka",
  "Nagoya",
  "Fukuoka",
  "Sapporo"
};
int size = sizeof( city[0] ); // 都市名文字列のサイズ
int num = sizeof( city ) / size; // 都市名の数
qsort( city, num, size, strcmp );
for ( int i = 0; i < num; i++ )
printf( "%s\n", city[i] );

結果は次のとおりです。
Fukuoka
Nagoya
Osaka
Sapporo
Tokyo

これに対して、たとえば、char *[n] 型の配列 (ポインタの配列) を strcmp で並べ替えることはできません。そのような配列を並べ替えるには、int func( char**, char** ) 型の比較関数を用意する必要があります。

void* bsearch( const void* key, const void* base, size_t num, size_t size, int (*cmp)(void*, void*) ); (stdlib.h)

二分検索のアルゴリズムで配列要素を検索します。配列は昇順にソートされている必要があります。サイズ size の要素が num 個並んだ配列 base から、値が key と一致する最初の要素を関数 cmp の判定に従って検索します。関数 cmp の形式は、qsortcmp と同じです。一致する要素がない場合は、NULL が返されます。

たとえば、上の city 配列から "Osaka" へのポインタを取得するには、次のように記述します。
char* ptr = (char*)bsearch( "Osaka", city, num, size, strcmp );

int rand( void ); (stdlib.h)
void
srand( unsigned seed );

rand は、0 〜 32767 (RAND_MAX) までの疑似乱数を生成します。srand に任意の unsigned 値を渡すことにより、生成される乱数系列を変更できます。srand を呼び出さない限り、rand は、プログラムを起動するたびに毎回同じ乱数系列を生成します。

_max( a, b ); (stdlib.h)
_min( a, b );

それぞれ 2 つの引数のうち大きい方と小さい方の値を返します。

次のようにマクロ定義されています。
#define _max( a, b )   ((a) >= (b) ? (a) : (b))
#define _min( a, b )   ((a) <= (b) ? (a) : (b))

offsetof( s, m ); (stddef.h)

構造体メンバのオフセットを取得するマクロ関数です。次の例のように使用します。
struct s { long a; short b; };
int x = offsetof( struct s, a ); // x = 0
int y = offsetof( struct s, b ); // y = 4

char* strerror( int errnum ); (string.h)

コンパイラごとに定義されるエラー コードの意味を説明する文字列を返します。Light C では、errnum に errno と同じエラー コードを指定します。

assert( ex ); (assert.h)

assert は、実行時に式の値をチェックするためのマクロで、デバッグ目的で使用します。ex の値が実行時に評価され、偽 (0) であれば指定した方法で通知されます。マクロ NDEBUG を定義してコンパイルすると、assert マクロは消去され、コードは生成されません。

-os:dos が有効な場合は、ex が偽に評価されると、最初にソース ファイル名と行番号が stderr に出力され、次に raise(SIGABRT) が呼び出されて、ランタイム エラー R.1100 でプログラムが終了します。

-os:none が有効な場合は、ex が偽に評価されると、単に raise(SIGABRT) が呼び出されます。この場合は、あらかじめ signal() で指定しておかない限り、何も行われません。
assert( ptr != NULL ); // ポインタが NULL でないことを確認
assert( ptr ); // 同上
assert( 0 ); // このコードが実行されたら常に失敗
#define NDEBUG
assert( 0 ); // この assert マクロは無効

void abort( void ); (stdlib.h)

raise( SIGABRT) を呼び出すことにより、プログラムをコード 2 (EXIT_FAILURE) で異常終了させます。この動作は、signal 関数で変更できます。

void va_start( va_list lst, arg ); (stdarg.h)
type
va_arg( va_list lst, type );
void
va_end( va_list lst );

可変個の引数を受け取る関数の引数にアクセスするときに使用します。

まず、va_list 型の変数を宣言します。va_list は、stdarg.h で char* と定義されています。その後、最後の固定引数とともに va_start を呼び出すことにより、可変引数の先頭を知らせます。次に、va_arg を繰り返し呼び出して、可変引数を順に取得します。type には各可変引数の型の名前 (int など) を指定します。最後に、va_end を呼び出して、処理の終了を知らせます (省略可能)。
void message( int num, ...) {
  va_list lst;
  va_start( lst, num );
  for ( int i = 0; i < num; i++ ) {
    char* a = va_arg( lst, char* );
    printf( "[%s]", a );
  }
  va_end( lst );
}
main() {
  message( 3, "A", "BC", "123" ); // "[A][BC][123]" と表示される
}

long _asmcode( void far* code, long data ); (stdlib.h)

機械語コードを直接実行します。code には、実行する機械語コードのアドレスを指定します。data は、機械語コードに DX:AX レジスタで渡されます。機械語コードで DX:AX に値を設定すると、その値が _asmcode の戻り値になります。機械語コードでは、最後に RETF (far リターン) 命令 CBh を実行する必要があります。
_asmcode( "\xE6\x03\xCB", 123 );
// 03 番ポートに 123 を出力して far リターン
// ("out 3, al" + "retf")

参照   インライン アセンブラレジスタの保存