[C言語 標準ライブラリ] stdlib.hの使い方

※本ブログでは、商品・サービスのリンク先にプロモーションを含みます。

スポンサーリンク

stdlib.hは一般的な実用性を持つマクロ、型、関数が宣言および定義されています。

スポンサーリンク

マクロ

NULL

空(NULL)ポインタ定数です。
stddef.h、locale.h、stdio.h、stdlib.h、string.h、time.h、wchar.hで定義されています。

EXIT_FAILURE

失敗終了状態であることを示します。
exit関数の実引数として使用します。

EXIT_SUCCESS

成功終了状態であることを示します。
exit関数の実引数として使用します。

RAND_MAX

rand関数が返す最大値を示します。

MB_CUR_MAX

その時のロケール(LC_CTYPEカテゴリ)の拡張文字集合におけるマルチバイト文字の最大バイト数を表す正の整数式に展開されるオブジェクト形式のマクロです。
この値がMB_LEN_MAXを超えることはありません。

size_t

sizeof演算子が生成する結果を表すための符号無し整数型です。
stddef.h、stdio.h、stdlib.h、string.h、time.h、wchar.hで定義されます。

wchar_t

処理系がサポートするロケールの中で最も大きな拡張文字集合のすべての要素に対して、区別可能なコードを表現できる値の範囲をもつ整数型です。
この型では、NULL文字はコード値0を持ちます。
stddef.h、stdlib.h、wchar.hで定義されます。

div_t

div関数が返す値を表す型です。
次のメンバを含む構造体です。

メンバ名説明
intquot商です。
intrem剰余です。

ldiv_t

ldiv関数が返す値を表す型です。
次のメンバを含む構造体です。

メンバ名説明
longquot商です。
longrem剰余です。

lldiv_t

lldiv関数が返す値を表す型です。
次のメンバを含む構造体です。

メンバ名説明
long longquot商です。
long longrem剰余です。
スポンサーリンク

数値変換関数

double atof(const char *nptr)

引数nptrが指す文字列をdouble型フォーマットに変換します。
エラー時の動作を除けば、以下の関数と同等です。

strtod(nptr, (char **)NULL);

変換された値が返されます。

使用例:

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

int main(void)
{
    const char *str1 = "123.456";
    const char *str2 = "789.012";

    double num1 = atof(str1);
    double num2 = atof(str2);

    printf("%f + %f = %f\n", num1, num2, num1 + num2);

    return 0;
}

実行結果:

123.456000 + 789.012000 = 912.468000

int atoi(const char *nptr)

定義:

int atoi(const char *str);             // int版
long int atol(const char *str);        // long版
long long int atoll(const char *str);  // long long版

引数nptrが指す文字列をint型フォーマットに変換します。
エラー時の動作を除けば、以下の関数と同等です。

strtol(nptr, (char **)NULL, 10);

strtol(nptr, (char **)NULL, 10);

strtoll(nptr, (char **)NULL, 10)

変換された値が返されます。

使用例:

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

int main(void)
{
    const char *str1 = "123";
    const char *str2 = "789";

    int num1 = atoi(str1);
    int num2 = atoi(str2);

    printf("%d + %d = %d\n", num1, num2, num1 + num2);

    return 0;
}

実行結果:

123 + 789 = 912

double strtod(const char *nptr, char **endptr)

定義:

float strtof(const char *nptr, char **endptr);         // float版
double strtod(const char *nptr, char **endptr);        // double版
long double strtold(const char *nptr, char **endptr);  // long double版

引数nptrが指す文字列をdouble型フォーマットに変換します。
まず、入力文字列が次の3つに分けられます。
・最初の省略可能な空白の連続
・変換の対象となる浮動小数点定数の形をした部分(この部分を以後「主体」と呼ぶ)
・最後にあるNULL文字を含む認識されない文字列。
次に、主体となる部分を浮動小数点数に変換し、結果が返されます。

変換可能な主体の形は次の通りです。
・省略可能な正か負の符号
・それに続く数字の連なり
・省略可能な指数部
前述の主体が取るべき形は、空白以外の文字で始まる入力内で最長の部分文字列として定義されます。
入力文字列の中身が無いとか、空白ばかりであるとか、最初の空白でない文字が符号や数字や小数点でない場合には、主体はありません。

主体が変換可能であれば、最初の数字か小数点から後は、以下の点を除いて浮動小数点定数と同じように解釈されます。すなわち、小数点はピリオドとして扱われ、小数点も指数部も無い場合には数字の最後の桁の後に小数点があるものとして扱われます。主体が負の符号で始まる場合、変換後の数値は負になります。
endptrがNULLでなければ、最後の文字列へのポインタがendptrが指すオブジェクトに格納されます。

“C”ロケール以外では処理系定義の主体の形が追加対応されていてもよい。

主体がない場合や変換可能でない場合は変換は行われず、endptrがNULLでなければ、nptrの値がendptrが指すオブジェクトに格納されます。

存在するならば変換された値が返されます。
変換できなかった場合は、0が返されます。
本来の数値が表現可能な範囲を超えていた場合は、正か負のHUGE_VALが返され、errnoにはERANGEが格納されます。
アンダーフローを起こした場合は、0が返され、errnoにはERANGEが格納されます。

使用例:

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

int main(void)
{
    const char *str1 = "123.456";
    const char *str2 = "789.012xyz";

    char *endptr;

    errno = 0; // errnoをリセット
    double num1 = strtod(str1, &endptr);
    if(errno == ERANGE){
        printf("オーバーフローが発生しました。(%s)\n", str1);
        return 1;
    }

    if(endptr == str1){
        printf("桁の数字が見つかりませんでした。(%s)\n", str1);
        return 1;
    }

    errno = 0; // errnoをリセット
    double num2 = strtod(str2, &endptr);
    if(errno == ERANGE){
        printf("オーバーフローが発生しました。(%s)\n", str2);
        return 1;
    }

    if(endptr == str2){
        printf("桁の数字が見つかりませんでした。(%s)\n", str2);
        return 1;
    }

    printf("認識できない文字(%c)\n", *endptr);
    printf("%f + %f = %f\n", num1, num2, num1 + num2);

    return 0;
}

実行結果:

認識できない文字(x)
123.456000 + 789.012000 = 912.468000

このプログラムでは、まず文字列 “123.456” と “789.012xyz” を定義します。そして、strtod関数でそれらの文字列をdouble型の浮動小数点数に変換します。変換は数値が見つかるところまで行われ、数値に続く最初の未認識文字は endptr が指す場所になります。したがって、endptr が元の文字列と同じ場所を指している場合、変換が行われていないことを示します。また、変換中にオーバーフローが発生した場合、errnoがERANGEに設定されるので、それをチェックします。最後に読み込んだ数字とその和を表示します。

long int strtol(const char *nptr, char **endptr, int base)

定義:

long int strtol(const char *nptr, char **endptr, int base);              // int版
unsigned long strtoul(const char *nptr, char **endptr, int base);        // unsigned long版
long long strtoll(const char *nptr, char **endptr, int base);            // long long版
unsigned long long strtoull(const char *nptr, char **endptr, int base);  // unsigned long long版

引数nptrが指す文字列の最初の部分をlong int型フォーマットに変換します。
まず、入力文字列が次の3つに分けられます。
・最初の、省略可能な空白の連続
・変換の対象となるbaseによるある基数の整数定数の形をした部分(この部分を以後「主体」と呼ぶ)
・最後にあるNULL文字を含む認識されない文字列
次に、主体となる部分を整数に変換し、結果が返されます。

baseの値が0ならば、変換可能な主体の形は以下の点を除いた整数定数と同じです。
すなわち、省略可能な正か負の符号を持てるということと、整数接尾辞がないということです。
baseの値が2と36の間であれば、変換可能な主体の形は以下の点を満たすbaseを基数とする文字と数字の連続です。
すなわち、省略可能な正か負の符号を持てるということと、整数接尾辞がないということです。
a(またはA)からz(またはZ)までの文字は10から35までの数値を表します。
表す数字がbaseより小さい文字のみ許されます。
baseの値が16なら、0xまたは0Xの接頭辞が符号の後にについていてもよい。

前述の主体が取るべき形は、空白以外の文字で始まる入力内で最長の部分文字列として定義されます。
入力文字列の中身が無いとか、空白ばかりであるとか、最初の空白でない文字が符号や許される文字や数字でない場合には、主体はありません。

主体が変換可能でbaseの値が0ならば、最初の数字から後は整数定数と同じように解釈されます。
主体が変換可能でbaseの値が2と36の間であれば、これは変換の基数として使われ、各文字の値は前述した通りです。
主体が負の符号で始まる場合、変換後の数値は負になります。
endptrがNULLでなければ、最後の文字列へのポインタがendptrが指すオブジェクトに格納されます。

“C”ロケール以外では処理系定義の主体の形が追加対応されていてもよい。

主体がない場合や変換可能でない場合は変換は行われず、endptrがNULLでなければ、nptrの値がendptrが指すオブジェクトに格納されます。

存在するならば変換された値が返されます。
変換できなかった場合は、0が返されます。
本来の数値が表現可能な範囲を超えていた場合、LONG_MAXかLONG_MINが返され、errnoにはERANGEが格納されます。

使用例:

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

int main(void)
{
    const char *str1 = "123";
    const char *str2 = "789xyz";

    char *endptr;

    errno = 0; // errnoをリセット
    long num1 = strtol(str1, &endptr, 10);
    if(errno == ERANGE){
        printf("オーバーフローが発生しました。(%s)\n", str1);
        return 1;
    }

    if(endptr == str1){
        printf("桁の数字が見つかりませんでした。(%s)\n", str1);
        return 1;
    }

    errno = 0; // errnoをリセット
    long num2 = strtol(str2, &endptr, 10);
    if(errno == ERANGE){
        printf("オーバーフローが発生しました。(%s)\n", str2);
        return 1;
    }

    if(endptr == str2){
        printf("桁の数字が見つかりませんでした。(%s)\n", str2);
        return 1;
    }

    printf("認識できない文字(%c)\n", *endptr);
    printf("%ld + %ld = %ld\n", num1, num2, num1 + num2);

    return 0;
}

実行結果:

認識できない文字(x)
123 + 789 = 912

このプログラムでは、まず文字列 “123” と “789xyz” を定義します。そして、strtol関数でそれらの文字列をlong int型の整数に変換します。変換は数値が見つかるところまで行われ、数値に続く最初の未認識文字は endptr が指す場所になります。したがって、endptr が元の文字列と同じ場所を指している場合、変換が行われていないことを示します。また、変換中にオーバーフローが発生した場合、errnoがERANGEに設定されるので、それをチェックします。最後に読み込んだ数字とその和を表示します。

スポンサーリンク

擬似乱数列生成関数

int rand(void)

0~RAND_MAXの間の連続擬似乱数を発生させます。
整数の擬似乱数が返されます。
(RAND_MAXマクロ値は32767以上です)

使用例:

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

int main(void)
{
    srand(time(NULL));  // 乱数生成器の初期化

    for(int i=0; i<10; i++) {
        int random_number = rand();  // ランダムな整数の生成
        printf("%d\n", random_number);
    }

    return 0;
}

実行結果:

8508
29891
12554
6934
30204
31002
22403
23407
12003
8395

このプログラムは、10個のランダムな整数を生成し、それらを表示します。srand関数の引数には現在の時刻(time(NULL))を使用しているため、プログラムが実行されるたびに異なる数値が生成されます。

しかし、rand関数は生成する乱数の品質があまり高くないという問題があります。高品質の乱数が必要な場合は、より良い乱数生成アルゴリズムを実装するか、それを提供するライブラリを探すことをお勧めします。

void srand(unsigned int seed)

seedをrand関数が返す新しい乱数列のシードとして使用します。
srandが同じシード値で呼ばれるならば、乱数列も同じものが繰り返されます。
srandよりもrandが先に呼ばれた場合、srandに1を渡したのと同じ乱数列が発生します。

使用例はrand関数を参照してください。

記憶域管理関数

void *calloc(size_t nmemb, size_t size)

動的メモリを確保し、0クリアします。
nmemb個のsizeの大きさのオブジェクトの配列のための空間を確保します。
空間の全てのビットは0に初期化されます。
成功したときは確保された領域へのポインタが返され、失敗したときはNULLポインタが返されます。

使用例:

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

int main(void)
{
    int n = 10; // 配列の要素数
    int *array = (int*)calloc(n, sizeof(int)); // n要素のint型配列のメモリを確保

    // メモリ確保の確認
    if(array == NULL){
        printf("メモリの確保に失敗しました。\n");
        return 1;
    }

    // 配列の要素を表示
    for(int i=0; i<n; i++){
        printf("array[%d] = %d\n", i, array[i]);
    }

    // メモリの解放
    free(array);

    return 0;
}

実行結果:

array[0] = 0
array[1] = 0
array[2] = 0
array[3] = 0
array[4] = 0
array[5] = 0
array[6] = 0
array[7] = 0
array[8] = 0
array[9] = 0

void free(void *ptr)

確保された動的メモリ領域を開放します。
ptrが指す空間を確保されていない状態に戻します。
この領域は、以降の確保に使えるようになります。
ptrがNULLポインタである場合は何も起きません。
calloc、malloc、reallocのいずれの返り値でもなかった場合、 またはfreeかreallocによって領域が開放されていた場合の動作は未定義です。

使用例はmalloc関数を参照してください。

void *malloc(size_t size)

動的メモリを確保します。
sizeの大きさのオブジェクトのための空間を確保します。
オブジェクトの値は不定です。
成功したときは確保された領域へのポインタが返され、失敗したときはNULLポインタが返されます。

使用例:

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

int main(void)
{
    int n = 10;
    int *array = (int*)malloc(n * sizeof(int));  // n個のint型要素のメモリを確保

    // メモリ確保の確認
    if(array == NULL){
        printf("メモリの確保に失敗しました。\n");
        return 1;
    }

    // 配列に値を設定
    for(int i=0; i<n; i++){
        array[i] = i;
    }

    // 配列の要素を表示
    for(int i=0; i<n; i++){
        printf("array[%d] = %d\n", i, array[i]);
    }

    // メモリの解放
    free(array);
    array = NULL;  // ダングリングポインタを防ぐためにNULLを設定

    return 0;
}

実行結果:

array[0] = 0
array[1] = 1
array[2] = 2
array[3] = 3
array[4] = 4
array[5] = 5
array[6] = 6
array[7] = 7
array[8] = 8
array[9] = 9

void *realloc(void *ptr, size_t size)

動的メモリを再確保します。
ptrで指定されるオブジェクトのサイズをsizeに変更します。
変更前と後での小さいほうのサイズまでの内容は変化しません。
変更後のサイズのほうが大きかった場合、新たに確保された部分の内容は不定です。
ptrがNULLポインタであれば、この関数は引数にsizeを渡したmallocと同等です。
NULLポインタでなく、calloc、malloc、reallocのいずれの返り値でもないか、freeかreallocによって開放されていた場合の動作は未定義です。
確保できない場合、ptrの指すオブジェクトは変更されません。
sizeが0でptrがNULLポインタでない場合は、オブジェクトは開放されます。
成功したときは移動したかもしれない領域へのポインタが返され、失敗したときはNULLポインタが返されます。

使用例:

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

int main(void)
{
    int n = 5;
    int *array = (int*)malloc(n * sizeof(int));  // n個のint型要素のメモリを確保

    // メモリ確保の確認
    if(array == NULL){
        printf("メモリの確保に失敗しました。\n");
        return 1;
    }

    // 配列に値を設定
    for(int i=0; i<n; i++){
        array[i] = i;
    }

    // 配列を拡張する
    int new_n = n * 2;
    int *new_array = (int*)realloc(array, new_n * sizeof(int));  // メモリの再確保

    // メモリ確保の確認
    if(new_array == NULL){
        printf("メモリの再割り当てに失敗しました。\n");
        free(array);  // 元のメモリを解放
        return 1;
    }else{
        array = new_array;  // 新たに確保したメモリのアドレスを保存
    }

    // 新たに確保した領域に値を設定
    for(int i=n; i<new_n; i++){
        array[i] = i;
    }

    // 配列の要素を表示
    for(int i=0; i<new_n; i++){
        printf("array[%d] = %d\n", i, array[i]);
    }

    // メモリの解放
    free(array);

    return 0;
}

実行結果:

array[0] = 0
array[1] = 1
array[2] = 2
array[3] = 3
array[4] = 4
array[5] = 5
array[6] = 6
array[7] = 7
array[8] = 8
array[9] = 9
スポンサーリンク

環境に関連する関数