★関数(引数と戻り値4)★


アドレスを返す関数を1つ紹介します。

以前、strchrという関数を紹介しました。

文字列の中に指定した文字が入っているかどうか調べる関数です。

strchr関数のプロトタイプ宣言を確認すると、

char* strchr(char* _String, int _Ch);

となっています。

※分かりやすくするために、省略して表示しています。

引数は、「char* _String」が文字列の先頭番地を渡すポインタ変数です。

メモリアドレス」にも書いてありますが、配列には連続したアドレスが割り当てられています。

配列を関数に渡すには、配列の先頭のアドレスを渡すようになります。

※これは後ほど詳しく書きます。

もう1つの引数「int _Ch」が探したい文字です。

文字ならchar型では?と思いますが、今は気にしないでください。

そして、戻り値は「char*」です。

「char型のアドレスを返す」という意味です。

どのようなアドレスが返ってくるのか、実際にプログラムを実行しながら確認しましょう。


まずは文字列を用意して、それぞれの番地を確認するプログラムを作成します。

<sample program 137-01>

#include <stdio.h>

int main(void)
{
    char str[] = "ABCDE";

    int i;

    for (i = 0; i < 5; i++) {
        printf("str[%d] Address = %p\n", i, &str[i]);
    }

    return 0;
}

<実行結果>

str[0] Address = 00ADFCDC
str[1] Address = 00ADFCDD
str[2] Address = 00ADFCDE
str[3] Address = 00ADFCDF
str[4] Address = 00ADFCE0
続行するには何かキーを押してください・・・

※実行結果は毎回変わる可能性があります。


次に、strchr関数を使って文字'C'を探すプログラムを作ります。

以前のプログラムでは、if文の条件にstrchr関数を入れて作りました。

同じ要領で作ってみます。

<sample program 137-02>

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[] = "ABCDE";

    int i;

    for (i = 0; i < 5; i++) {
        printf("str[%d] Address = %p\n", i, &str[i]);
    }

    if (strchr(str, 'C')) {
        printf("ありました!\n");
    }
    else {
        printf("ありませんでした!\n");
    }

    return 0;
}

<実行結果>

str[0] Address = 00A5FBC8
str[1] Address = 00A5FBC9
str[2] Address = 00A5FBCA
str[3] Address = 00A5FBCB
str[4] Address = 00A5FBCC
ありました!
続行するには何かキーを押してください・・・

※実行結果は毎回変わる可能性があります。


このif文が成り立つ、という事は「0」以外の数値が返ってきているということです。

実際にポインタ変数を追加して受け取ってみましょう。

<sample program 137-03>

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[] = "ABCDE";

    int i;

    char *p;

    for (i = 0; i < 5; i++) {
        printf("str[%d] Address = %p\n", i, &str[i]);
    }

    p = strchr(str, 'C');

    printf("p = %p\n", p);

    if (strchr(str, 'C')) {
        printf("ありました!\n");
    }
    else {
        printf("ありませんでした!\n");
    }

    return 0;
}

<実行結果>

str[0] Address = 00B4FE08
str[1] Address = 00B4FE09
str[2] Address = 00B4FE0A
str[3] Address = 00B4FE0B
str[4] Address = 00B4FE0C
p = 00B4FE0A
ありました!
続行するには何かキーを押してください・・・

※実行結果は毎回変わる可能性があります。


戻り値を受け取ったポインタ変数pの中には、配列の「C」が入っている番地が入っていました。

strchr関数とは、発見した文字のアドレスを返す関数だったのです。

このアドレスは元々main関数で用意されているアドレスなので、strchr関数が完了しても領域が解放される訳ではありません。

このように安全な状況でアドレスを返す事が出来るのであれば、アドレスを返す関数を作っても問題ありません。


ついでに、見つからなかった場合は何が返ってきているのか確認しましょう。

<sample program 137-04>

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[] = "ABCDE";

    int i;

    char *p;

    for (i = 0; i < 5; i++) {
        printf("str[%d] Address = %p\n", i, &str[i]);
    }

    p = strchr(str, 'G');

    printf("p = %p\n", p);

    if (strchr(str, 'G')) {
        printf("ありました!\n");
    }
    else {
        printf("ありませんでした!\n");
    }

    return 0;
}

<実行結果>

str[0] Address = 0026FDBC
str[1] Address = 0026FDBD
str[2] Address = 0026FDBE
str[3] Address = 0026FDBF
str[4] Address = 0026FDC0
p = 00000000
ありませんでした!
続行するには何かキーを押してください・・・

※実行結果は毎回変わる可能性があります。


当然、if文が成り立たなくなるので「0」が返ってきているのですが、この「0」には意味があります。

C言語の環境によっては「NULL」という定数が用意されていることがあります。

※Visual Studio Community 2015では、「vcruntime.h」で定義されており「stdio.h」などをincludeすると自動的にincludeされます。

この「NULL」は、

#define NULL 0

と定義されており、「0」であることが分かります。

意味としては「無効なアドレス」という意味を持っています。

「0番地」という特殊なアドレスで、使えないアドレスということです。


アドレスを返す関数の多くは、失敗した場合などに「NULL」を返す事が多いです。

ファイルの所で、fopen関数も失敗した時に「NULL」を返していましたね。

上のプログラムも「NULL」を使って書き換えると、↓のようになります。

<sample program 137-05>

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[] = "ABCDE";

    char *p;

    p = strchr(str, 'D');

    if (p != NULL) {
        printf("ありました!\n");
    }
    else {
        printf("ありませんでした!\n");
    }

    return 0;
}

<実行結果>

ありました!
続行するには何かキーを押してください・・・

次へ

戻る

目次へ