#stdlib.h

型のエイリアスとマクロ

stdlib.h は次の型の別名を定義します。

  • size_t: sizeof の戻り値の型。
  • wchar_t: ワイド文字タイプ。

stdlib.h は次のマクロを定義します。

  • NULL: ヌルポインタ。
  • EXIT_SUCCESS: 関数が正常に実行された場合の終了ステータス。
  • EXIT_FAILURE: 関数の実行時にエラーが発生した場合の終了ステータス。
  • RAND_MAX: rand() 関数が返すことができる最大値。
  • MB_CUR_MAX: 現在のロケールでマルチバイト文字が占める最大バイト数。

abs()、labs()、llabs()

これら 3 つの関数は、整数の絶対値を計算するために使用されます。 int型の場合はabs()、long int型の場合はlabs()、long long int型の場合はllabs()を使用します。

int abs(int j);
long int labs(long int j);
long long int llabs(long long int j);

以下に使用例を示します。

// 出力 |-2| = 2
printf("|-2| = %d\n", abs(-2));

// 出力 |4| = 4
printf("|4| = %d\n", abs(4));

div()、ldiv()、lldiv()

これら 3 つの関数は、2 つのパラメータの商と余りを計算するために使用されます。 int型の除算にはdiv()、long int型の除算にはldiv()、long long int型の除算にはlldiv()を使用します。

div_t div(int 数値, int denom);
ldiv_t ldiv(long int 数値、long int denom);
lldiv_t lldiv(long long int 数値、long long int denom);

これらの関数は、2 番目の引数 (分母) を最初の引数 (分子) で割り、商と余りを生成します。これら 2 つの値はデータ構造を通じて返され、「div()」は div_t 構造を返し、「ldiv()」は ldiv_t 構造を返し、「lldiv()」は lldiv_t 構造を返します。

これらの構造体には次の 2 つのフィールドが含まれます。

int; // 商;
int rem // 剰余

それらの完全な定義は次のとおりです。

typedef 構造体 {
  int quot、レム;
} div_t;
    
typedef 構造体 {
  長い int 引用、レム;
ldiv_t;
    
typedef 構造体 {
  Long Long int quot、レム;
lldiv_t;

ここに例を示します。

div_t d = div(64, -7);

// 出力 64 / -7 = -9
printf("64 / -7 = %d\n", d.quot);

// 64 % -7 = 1 を出力します
printf("64 %% -7 = %d\n", d.rem);

##文字列を数値に変換する

一連の関数

stdlib.h は、文字列を数値に変換できる一連の関数を定義します。

  • atoi(): 文字列をint型に変換します。
  • atof(): 文字列をdouble型に変換します。
  • atol(): 文字列をlong int型に変換します。
  • atoll(): 文字列をlong long int型に変換します。

それらのプロトタイプは次のとおりです。

int atoi(const char* nptr);
double atof(const char* nptr);
long int atol(const char* nptr);
Long Long int atoll(const char* nptr);

上記の関数のパラメータはすべて文字列ポインタであり、文字列の先頭のスペースは無視され、変換は最初の無効な文字で停止します。関数名の「a」は ASCII を表し、「atoi()」は「ASCII から int へ」を意味します。

変換された数値を返すか、文字列が変換できない場合は「0」を返します。

以下に使用例を示します。

atoi("3490") // 3490
atof("3.141593") // 3.141593

パラメータが数字で始まる文字列の場合、atoi() は数値部分のみを変換します。たとえば、atoi("42regulator") は整数 42 を返します。 「hello world」など、最初の文字が数字でない場合は、「0」が返されます。

str級関数(浮動小数点数変換)

stdlib.h は、より強力な浮動小数点数変換関数も定義しています。

  • strtof(): 文字列を float 型に変換します。
  • strtod(): 文字列をdouble型に変換します。
  • strtold(): 文字列をlong double型に変換します。

それらのプロトタイプは次のとおりです。

float strtof(
  const char* 制限 nptr、
  char** 制限 endptr
);

ダブルストラット(
  const char* 制限 nptr、
  char** 制限 endptr
);
    
long double strtold(
  const char* 制限 nptr、
  char** 制限 endptr
);

これらはすべて 2 つのパラメータを受け入れます。最初のパラメータは変換する必要がある文字列で、2 番目のパラメータは元の文字列の変換できない部分を指すポインタです。

  • nptr: 変換される文字列 (先頭の空白文字は無視されます)。
  • endprt: 変換不可能な部分の最初の文字へのポインタ。文字列を数値に完全に変換できる場合、このポインタは文字列の末尾にあるターミネータ \0 を指します。このパラメータが NULL に設定されている場合、文字列の残りの部分を処理する必要がないことを意味します。

戻り値は変換された値です。文字列が変換できない場合は、「0」が返されます。変換の結果としてオーバーフローが発生した場合、errno は ERANGE に設定されます。値が大きすぎる場合 (正または負)、関数は HUGE_VAL を返します。値が小さすぎる場合、関数はゼロを返します。

char *inp = "123.4567abdc";
char *badchar;

double val = strtod(inp, &badchar);

printf("%f\n", val); // 123.456700
printf("%s\n", badchar); // abdc

文字列が完全に変換できた場合、第 2 引数は \0 を指すので、次の書き方で完全に変換されたかどうかを判断できます。

if (*endptr == '\0') {
  // 完全な変換
} それ以外 {
  // 変換できない文字があります
}

未変換部分を気にしない場合は、endptr を NULL に設定できます。

これらの関数は、文字列を特別な値 Infinity および NaN に変換することもできます。文字列に INF または INFINITY (大文字または小文字) が含まれる場合は Infinity に変換され、文字列に NAN が含まれる場合は NaN が返されます。

str級数関数(整数変換)

str シリーズの関数には、整数変換に対応する関数もあります。

  • strtol(): 文字列をlong int型に変換します。
  • strtoll(): 文字列をlong long int型に変換します。
  • strtoul(): 文字列を unsigned long int 型に変換します。
  • strtoull(): 文字列を unsigned Long Long int 型に変換します。

それらのプロトタイプは次のとおりです。

long int strtol(
  const char* 制限 nptr、
  char** 制限 endptr、
  整数ベース
);
    
Long Long int strtoll(
  const char* 制限 nptr、
  char** 制限 endptr、
  整数ベース
);
    
unsigned long int strtoul(
  const char* 制限 nptr、
  char** 制限 endptr、
  整数ベース
);
    
unsigned long long int strtoull(
  const char* 制限 nptr、
  char** 制限 endptr、int ベース
);

3 つのパラメータを受け入れます。

(1) nPtr: 変換される文字列 (先頭の空白文字は無視されます)。

(2) endPrt: 変換できない部分の先頭文字を指すポインタ。文字列を数値に完全に変換できる場合、このポインタは文字列の末尾にあるターミネータ \0 を指します。このパラメータが NULL に設定されている場合、文字列の残りの部分を処理する必要がないことを意味します。

(3) base: 変換される整数の底。この値は、対応する基数を表す「2」から「36」までの整数である必要があります。それが特別な値「0」の場合、関数が値の接頭辞に基づいて基数を独自に決定できることを意味します。つまり、数値の接頭辞「0」が付いている場合は 8 進数であり、数値の接頭辞「0x」または「0X」が付いている場合は 16 進数です。

戻り値は変換された値です。変換が失敗した場合は '0' が返されます。

以下は 10 進整数を変換する例です。

char* s = "3490";
unsigned long int x = strtoul(u, NULL, 10);

printf("%lu\n", x);

以下は 16 進整数を変換する例です。

char* 終了;

長い値 = strtol("0xff", &end, 16);
printf("%ld\n", 値); // 255
printf("%s\n", end); // コンテンツがありません

値 = strtol("0xffxx", &end, 16);
printf("%ld\n", 値); // 255
printf("%s\n", end);

上の例では、strtol() は文字列に 16 進整数が含まれていることを指定できます。変換できない部分には、ポインタ「end」を使用してアクセスできます。

以下は 2 進整数を変換する例です。

char* s = "101010";
unsigned long int x = strtoul(s, NULL, 2);

printf("%lu\n", x);

以下は、関数自身で整数の基数を決定させる例です。

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

int main(void) {
  const char* 文字列 = "-1234567abc";
  char* 残りPtr;
  long x = strtol(string, &remainderPtr, 0);
  printf("%s\"%s\"\n%s%ld\n%s\"%s\"\n",
    "元の文字列は ",
    弦、
    "変換された値は ",
    ×、
    "元の文字列の残りは ",
    残りPtr
  );
}

上記のコードの出力は次のようになります。

元の文字列は「-1234567abc」です
変換された値は -1234567 です
元の文字列の残りの部分は「abc」です

変換された値が大きすぎる場合、strtol() 関数は値 ERANGEerrno に格納し、LONG_MIN (元の値は負の数) または LONG_MAX (元の値は正の数) を返します。数値)、 strtoul()ULONG_MAX を返します。

ランド()

rand() 関数は、0 から RAND_MAX までのランダムな整数を生成するために使用されます。 RAND_MAXstdlib.h で定義されたマクロで、通常は INT_MAX と等しくなります。

// プロトタイプ
int rand(void);

// 例
int x = rand();

NからMまでの整数(NとMの2つのエンドポイント値を含む)の間の乱数を取得したい場合は、次の記述方法を使用できます。

int x = rand() % (M - N + 1) + N;

たとえば、1 から 6 までの乱数は次のように記述されます。

int x = rand() % 6 + 1;

浮動小数点数のランダムな値を取得するには、次の記述方法を使用できます。

// 0 から 0.999999 までの乱数
printf("0 ~ 0.99999: %f\n", rand() / ((float)RAND_MAX + 1));

// n と m の間の乱数:
// n + m * (rand() / (float)RAND_MAX)
printf("10.5 ~ 15.7: %f\n", 10.5 + 5.2 * rand() / (float)RAND_MAX);

上記の例では、rand()RAND_MAX は両方とも int 型であるため、明示的な型変換を使用して浮動小数点数に変換します。

スランド()

rand() は擬似乱数関数です。ランダム性を高めるには、呼び出す前に srand() 関数を使用してシード値をリセットする必要があります。

srand() 関数はシード値として unsigned int を受け入れ、戻り値はありません。

void srand(unsigned int シード);

通常、time(NULL) 関数は、現在の時刻エポックからの秒数を srand() のパラメータとして返すために使用されます。

#include <time.h>
srand((unsigned int) time(NULL));

上記のコードでは、time() のプロトタイプはヘッダー ファイル time.h で定義されており、戻り値の型は型エイリアス time_t です。具体的な型はシステムに依存します。型を強制的に変換する必要があります。 time() のパラメータは、特定の time_t 型の時刻値を指すポインタです。ヌル ポインタ NULL がパラメータとして渡されます。NULL は通常 0 であるため、time と書くこともできます。 (0)

中止()

「abort()」は実行中のプログラムを異常終了させるために使用します。この関数を使用する目的は、SIGABRT 信号をトリガーすることであり、開発者はプログラム内でこの信号の処理関数を設定できます。

ボイド中止(ボイド);

この関数にはパラメータがありません。

exit()、quick_exit()、_Exit()

これら 3 つの関数は、現在実行中のプログラムを終了するために使用されます。

void exit(int ステータス);
void Quick_exit(int status);
void _Exit(int ステータス);

これらはすべて整数を受け入れ、プログラムの終了ステータスを示します。「0」は正常な終了を意味し、ゼロ以外の値はエラーを示します。マクロ「EXIT_SUCCESS」および「EXIT_FAILURE」をパラメータとして使用できます。それら自体には戻り値がありません。

両者の違いは退館時の清掃作業です。 exit() は通常の終了であり、システムはすべてのファイル ストリームの更新や一時ファイルの削除などの完全なクリーンアップを実行します。 quick_exit() は、システムのクリーニング作業をわずかに減らして迅速に終了します。 _Exit() はクリーンアップ作業を行わずにすぐに終了します。

ここではいくつかの使用例を示します。

終了(EXIT_SUCCESS);
クイック終了(EXIT_FAILURE);
_終了(2);

atexit()、at_quick_exit()

atexit() は、現在のプログラムが終了するときに実行される他の関数を登録するために使用されます (正常に終了するには、exit() または main() を呼び出します)。

at_quick_exit() は、quick_exit() メソッドを使用して現在のプログラムを終了するときに実行される他の関数を登録します。

exit()atexit() で登録された関数のみをトリガーでき、quick_exit()at_quick_exit() で登録された関数のみをトリガーできます。

int atexit(void (*func)(void));
int at_quick_exit(void (*func)(void));

パラメータは実行する関数のアドレス、つまり関数名です。戻り値は、呼び出しが成功した場合は「0」、呼び出しが失敗した場合は非ゼロです。

以下に例を示します。

void サインオフ(void);
void too_bad(void);

int main(void) {

  int n;
  atexit(sign_off); /*sign_off()関数を登録します */

  put("整数を入力してください:");
  if (scanf("%d", &n) != 1) {
    put("それは整数ではありません!");
    atexit(too_bad); /* too_bad() 関数を登録します */
    終了(EXIT_FAILURE);
  }

  printf("%d は %s.\n", n, (n % 2 == 0) ? "偶数" : "奇数");
  0を返します。
}

void サインオフ(void) {
  put("サインオフ");
}

void too_bad(void) {
  Puts(「残念すぎる」);
}

上の例では、ユーザー入力が失敗すると、sign_off() 関数と too_bad() 関数が呼び出されますが、入力が成功すると、sign_off() だけが呼び出されます。入力に失敗した場合のみ if 文を入力して too_bad() を登録するためです。

さらに、複数の atexit() ステートメントがある場合、関数が終了するときに最後に登録された関数が最初に呼び出されます。

atexit() で登録された関数 (上記の例の sign_offtoo_bad など) はパラメータをとらず、戻り値の型が void である必要があります。通常、これらの関数は、一時ファイルの削除や環境変数のリセットなど、いくつかのクリーンアップ タスクを実行します。

同じルールが at_quick_exit() にも適用されます。例を次に示します。

void exit_handler_1(void) {
  printf("1\n");
}

void exit_handler_2(void) {
  printf("2\n");
}

int main(void) {
  at_quick_exit(exit_handler_1);
  at_quick_exit(exit_handler_2);
  クイック終了(0);
}

上記の例を実行すると、コマンド ラインは最初に 2 を出力し、次に 1 を出力します。

getenv()

getenv() は環境変数の値を取得するために使用されます。環境変数は、オペレーティング システムによって提供されるプログラムの外部にある環境パラメータです。

char* getenv(const char* 名前);

そのパラメータは、環境変数の名前を表す文字列です。戻り値も、​​環境変数の値を表す文字列です。指定された環境変数が存在しない場合は、NULL が返されます。

以下は環境変数 $PATH の値を出力する例です。

printf("PATH は %s\n", getenv("PATH"));

システム()

system() 関数は外部プログラムを実行するために使用されます。オペレーティング システムのコマンド プロセッサによる実行のために、パラメータ文字列をオペレーティング システムに渡します。

void system(char const *コマンド);

この関数の戻り値はコンパイラによって異なります。ただし、標準では、パラメータとして NULL を使用する場合、使用可能なコマンド プロセッサがあるかどうかをオペレーティング システムに問い合わせ、ある場合はゼロ以外の値を返し、そうでない場合はゼロを返すと規定されています。

以下は ls コマンドの実行例です。

システム("ls -l");

メモリ管理機能

stdlib.h は、いくつかのメモリ操作関数を提供します。以下の関数の詳細については、「メモリ管理」の章を参照してください。残りの関数については、このセクションで説明します。

  • malloc(): メモリ領域の確保
  • calloc(): メモリ領域を割り当てます。
  • realloc(): メモリ領域のサイズを調整します。 ・free():メモリ領域を解放します。

aligned_alloc()

多くのシステムにはメモリ アライメント要件があります。つまり、メモリ ブロックのサイズは特定の値 (64 バイトなど) の倍数でなければならず、これは処理速度の向上に役立ちます。 aligned_alloc() は、メモリ アライメント要件を満たすメモリ ブロックを割り当てるために使用されます。そのプロトタイプは次のとおりです。

void* aligned_alloc(size_t アライメント, size_t サイズ);

2 つのパラメータを受け入れます。

  • アライメント: メモリ アライメントの単位サイズを示す整数。通常は 2 の整数乗 (2、4、8、16...)。
  • size: メモリブロックのサイズを示す整数。

割り当てが成功すると、新しく割り当てられたメモリ ブロックへの型なしのポインタが返されます。割り当てに失敗した場合は NULL が返されます。

char* p = aligned_alloc(64, 256);

上記の例では、aligned_alloc()で割り当てられるメモリブロックの単位サイズは64バイトであり、割り当てられるバイト数は256バイトである。

qsort()

qsort() は配列を素早くソートするために使用されます。この関数を使用すると、配列メンバーの型に関する要件はありません。任意の型の配列を並べ替えることができます。

void qsort(
  void *base、
  size_t nmemb、
  size_t サイズ、
  int (*比較)(const void *, const void *)
);

この関数は 4 つのパラメータを受け入れます。

  • Base: ソートする配列の先頭へのポインタ。
  • nmemb: 配列メンバーの数。
  • サイズ: 配列の各メンバーが占めるバイト単位の長さ。
  • compar: 2 つのメンバーを比較する関数を指す関数ポインタ。

比較関数 compar は、配列の 2 つのメンバーへのポインタを引数として受け取り、その 2 つのメンバーを比較します。最初の引数が 2 番目の引数より小さい場合、関数は負の値を返し、2 つの関数が等しい場合は '0' を返し、最初の引数が 2 番目の引数より大きい場合は正の数を返します。

以下に使用例を示します。

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

int compar(const void* elem0, const void* elem1) {
  const int* x = elem0;
  const int* y = elem1;
  
  *x - *y を返します。
}

int main(void) {
  int a[9] = {14, 2, 3, 17, 10, 8, 6, 1, 13};

  qsort(a, 9, sizeof(int), 比較);

  for (int i = 0; i < 9; i++)
    printf("%d ", a[i]);
  putchar('\n');
}

上記の例を実行すると、ソートされた配列「1 2 3 6 8 10 13 14 17」が出力されます。

bsearch()

bsearch() は二分探索を使用して配列内の値を検索します。この関数を使用すると、配列メンバーの型に関する要件はありません。任意の型の配列で値を検索できます。

このメソッドはソートされた配列に対してのみ機能することに注意してください。

void *bsearch(
  const void* キー、
  const void* ベース、
  size_t nmemb、
  size_t サイズ、
  int (*比較)(const void *, const void *)
);

この関数は 5 つのパラメータを受け入れます。

  • key: 検索する値へのポインタ。
  • Base: 配列の先頭へのポインタ。配列はソートされている必要があります。
  • nmemb: 配列メンバーの数。
  • サイズ: 配列の各メンバーが占めるバイト単位の長さ。
  • compar: 検索する値を他の値と比較する関数へのポインタ。

比較関数 compar は、最初の引数として検出される値を受け取り、2 番目の引数として比較される値を受け取ります。この関数は、最初の引数が 2 番目の引数より小さい場合は負の値を返し、2 つの引数が等しい場合は「0」を返し、最初の引数が 2 番目の引数より大きい場合は正の値を返します。

検索対象の値が見つかった場合、bsearch() はその値へのポインタを返し、見つからない場合は NULL を返します。

以下に使用例を示します。

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

int compar(const void *key, const void *value) {
  const int* k = キー;
  const int* v = 値;

  *k - *v を返します。
}

int main(void) {
  int a[9] = {2, 6, 9, 12, 13, 18, 20, 32, 47};

  int* r;
  int キー;

  キー = 12; // 配列に含まれます
  r = bsearch(&key, a, 9, sizeof(int), compar);
  printf("%d が見つかりました\n", *r);

  key = 30; // 配列には含まれません
  r = bsearch(&key, a, 9, sizeof(int), compar);
  if (r == NULL)
    printf("30 が見つかりませんでした\n");

  0を返します。
}

上記の例を実行すると、次の結果が出力されます。

12 件見つかりました
30個は見つかりませんでした

マルチバイト文字関数

stdlib.h には、マルチバイト文字を操作するための次の関数が用意されています。詳細については、「マルチバイト文字」の章を参照してください。

  • mblen(): マルチバイト文字のバイト長。
  • mbtowc(): マルチバイト文字をワイド文字に変換します。
  • wctomb(): ワイド文字をマルチバイト文字に変換します。
  • mbstowcs(): マルチバイト文字列をワイド文字列に変換します。
  • wcstombs(): ワイド文字列をマルチバイト文字列に変換します。

作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0