関数の引数としての配列

Home > 2005-09 / より良いC > This Entry [com : 3][Tb : 1]

2005-09-23

 Cでは、関数の引数として配列を渡すと、暗黙のうちにポインタに変換されてしまうため、配列の大きさ(要素数)も一緒に渡したい場合は、別の引数を用意しなければなりませんでした。C++でも基本的には同じなのですが、これから紹介するテクニックを用いることで、この問題を解消することが出来ます。

話を分かりやすくするために、配列の大きさを渡さないために問題を起こす代表格であるgets関数を改良してみることにします。
次のコードで定義されるmy_gets関数を見てください。

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

template <int N>
char* my_gets(char (&s)[N])
{
    int i;
    for (i = 0; i < N-1; i++)
    {
        int c = getchar();
        if (c == EOF || c == '\n')
            break;
        s[i] = c;
    }
    s[i] = '\0';
    return s;
}



my_gets関数の引数であるsは配列の参照です。そして、その要素数はテンプレート引数になっています。したがって、この関数にはmallocやnewで動的に割り付けたメモリブロックや、素性のよく分からないポインタを渡すことはできません。引数として渡すことができるのは配列型だけです。

こうすることで、配列の要素数を配列のアドレスとともに関数に渡すことができるわけです。

ところで、上の例では配列の要素数ごとに関数の実体ができてしまうため、プログラムサイズが肥大化してしまいます。現実には、配列の先頭アドレスとサイズを渡す共通の関数を用意し、my_gets関数テンプレート自体はインライン関数にするのがよいでしょう。

Comment

通りすがり : 2005-09-23(Fri) 23:15 URL edit
な、なるほど・・・。こういう手がありましたか。
管理人 : 2005-09-25(Sun) 18:20 URL edit
コメントありがとうございます。
配列型の参照というのは案外盲点になりがちです。C++では安易にstringやvectorを使ってしまうため、軽量な配列の存在を軽視しがちですが、組み込みでは普通の配列が使えるに越したことはありませんからね。
通りすがり : 2005-09-27(Tue) 01:26 URL edit
組み込みでは動的メモリ確保ができない場合もあってstringやvectorが使えるとも限りませんからね。
そんな時でも役に立つこうしたノウハウは大変参考になります。
Post a Comment









管理者にだけ表示を許可

Trackback

http://cppemb.blog17.fc2.com/tb.php/29-bc31b7b0

画期的な「虫除けスプレー」が欲しいな・・・。

C++でプログラムを組むと1発でコンパイルが通ることは なかなか無い(・・・私だけ!?)。 それどころか、コンパイルをすり抜けた虫(バグ)が実行ファイルの中に寄生する・・・。 その虫をキレイさっぱり退治するのがどんなに大変か・・・。 すぐに出てくる虫は即効退. ...

健康なエンジニアのブログ : 2005-09-26 00:14

C++と組み込み環境 | Page Top▲

New >>
volatileによる多重定義
<< old
非局所オブジェクトの初期化
ブログ内検索
RSSフィード