サイトマップ / C言語講座出入り口総目次目次:ヒープ領域>メモリの割り付

青い直線

メモリの割り付

青い直線

[クイックソート]←このソース→[ヒープというデータ構造]

/* ANSI C にない関数 */

/* 今日は、文字列をヒープ領域に保存する関数を作ります。ANSI C には、このようなライブラリ関数はありませんが、たいがいの処理系で用意されています。それは、このようなものです。

    #include <string.h>
    char  *strdup(const char *s);

    例:t = strdup(s);

    実行結果
    戻り値    複製した文字列へのポインタ

文字列は、例えば、下のように宣言します。

    char str[7] = "string";

文字の数より配列の要素の数が1多いのは、Cでは文字列の末尾にNULL文字 ( '\0' ) が追加されるからです。[ ] の中の 7 は、省略可能です。コンパイラが代わりに数えてくれます。配列の名前 'str' は、この配列の先頭アドレスになります。文字列を複製する関数へは、このアドレスを渡します。

渡された関数は、文字列の長さがわかりません。そこで、標準ライブラリ関数、strlen( ) を使って、文字列の長さを求めます。strlen( ) は、次のように定義されています。

    #include <string.h>
    size_t strlen(const char *s);
	
    例:n = strlen(s);

    実行結果    戻り値
    成功        s の長さ

strlen( ) は文字列 s の長さを返します。末尾の '\0' は数えません。

size_t は、string.h の中で、

    typedef unsigned size_t;

などと、型が宣言されています。文字列の長さがわかったら、文字列の長さ + 1 の char 型の配列 ( メモリブロック ) を用意します。 */

/* 注意深く使う関数 malloc( ) */

/* それには、標準ライブラリ関数 malloc( ) を使います。

malloc( ) は、実行時にヒープ領域に動的にメモリブロックを割り付けます。このブロックには、名前を付けることができません。そこで、ポインタを通してアクセスします。この理由で、malloc( ) は、注意深く使う関数です。malloc( ) を使っているルーチンにバグがあると、プログラム実行時に容易にクラッシュして、暴走します。

    #include <stdlib.h>
    void *malloc(size_t size);

    実行結果    戻り値
    成功        割り付けられたメモリブロックへのポインタ
    失敗        NULL

'void *' という記述が出てきました。'void *' は、ポインタを返すということです。しかし、特定の型のポインタではありません。下記のように使用します。

    p = (char *)malloc(size);     p: char 型ポインタ
    p = (short *)malloc(size);    p: short 型ポインタ
    p = (long *)malloc(size);     p: long 型ポインタ

ここまでを、C言語で記述すると、下記のようになります。

    t = (char *)malloc(strlen(s) + 1);

t は char 型のポインタです。文字列の長さ + 1 のメモリを割り付け、その先頭アドレスが t に代入されます。

次いで、割り付けられたメモリブロックに、文字列をコピーします。コピーするには、strcpy( ) を使います。

    #include <string.h>
    char *strcpy(char *s1, const char *s2);

    例:strcpy(s1, s2);

    実行結果    戻り値
    成功        s1 へのポインタ

strcpy( ) は、文字列 *s2 ( 末尾の '\0' を含む ) をs1 へコピーします。これで、文字列が複製されたことになります。最後に、複製された文字列へのポインタを返して、この関数は完成です。

malloc( ) で割り付けられたメモリブロックは、不要になった時点、あるいは、プログラムの終わりに、解放しなければなりません。解放するには、標準ライブラリ関数 free( ) を使います。

    #include <stdlib.h>
    void free(void *p);

    例:free(p);

    戻り値    なし

*/

/* ここからソースプログラム */

#include <stdio.h>
#include <stdlib.h>    /* malloc(  ) free(  ) で必要 */
#include <string.h>    /* strlen(  ) strcpy(  ) で必要 */

char *StringDup(const char *s);
void main(void);

  /* 文字列をヒープ領域に保存する */
char *StringDup(const char *s)
{
    char *t; /* malloc(  ) で割り付けられたメモリブロックへのポインタ */
    t = (char *)malloc(strlen(s) + 1);
    if (t == NULL)        /* 失敗したら */
        return (NULL);    /* NULL を返す */

    strcpy(t, s);
    return (t);           /* 複製された文字列へのポインタを返す */
}

void main(void)
{
    char str[ ] = " Duplicate a string.";
    char *t;

    printf("オリジナル文字列: %s\n", str);
      /* 複製された文字列へのポインタを t に代入 */
    t = StringDup(str);

    if (t != NULL)          /* 成功したら */
                            /* 複製された文字列を表示 */
        printf("複製された文字列: %s\n", t);
    else
        printf("メモリ不足!");

    free(t);	            /* メモリを解放 */
}

/* ここまでソースプログラム */

[クイックソート]←このソース→[ヒープというデータ構造]

青い直線

/* (C) 2000- YFプロ. All Rights Reserved. */    提供:C言語講座−それ自体コンパイルできる教材を使った講座です−

青い直線

サイトマップ / C言語講座出入り口総目次目次:ヒープ領域>メモリの割り付