2017年09月29日
《その56》 cstringライブラリ(p.306)
strlen関数
------------------------------------
文字列処理を行うライブラリ関数は、ヘッダで提供されています。
strlen関数は、文字列の長さを求めるための関数です。
ヘッダ #include <cstring>
形式 size_t strlen(const char* s);
解説 s が指す文字列の長さ(ナル文字は含まない)を求める。
返却値 求めた文字列の長さを返す。
------------------------------------p.306
この関数の実現例として、
------------------------------------
#include <cstddef>
size_t strlen(const char* s)
{
size_t len = 0;
while (*s++)
len++;
return len;
}
------------------------------------p.306
というコードが示されています。
#include <cstddef> は、size_t型 の定義のためと思われます。
この strlen関数の働きを確認するために、次のような簡単なプログラムを作りました。
// プログラム【1】
#include <cstddef>
#include <iostream>
using namespace std;
size_t strlen(const char* s)
{
size_t len = 0;
while (*s++)
len++;
return len;
}
int main()
{
char s[255];
cout << "文字列を入力 : "; cin >> s;
cout << "文字列\"" << s << "\"の長さ … " << strlen(s) << '\n';
}
予想通りの結果です。
ところが!! 上のプログラムの関数strlen を除去してしまっても、プログラムが問題なく動作することに気付いてしまいました!
#include <cstring> を記述してないので、
ライブラリ関数strlen は使えないと思っていたのですが・・・。
// プログラム【2】
#include <cstddef>
#include <iostream>
using namespace std;
/*
size_t strlen(const char* s)
{
size_t len = 0;
while (*s++)
len++;
return len;
}
*/
int main()
{
char s[255];
cout << "文字列を入力 : "; cin >> s;
cout << "文字列\"" << s << "\"の長さ … " << strlen(s) << '\n';
}
このプログラムで、全く同じ結果が得られてしまいます。
ということは、「ライブラリ関数strlen」 と 「プログラムに記述したstrlen関数」 が同居していたことになります。
では、最初の プログラム【1】では、いったいどちらの strlen関数が使われたのか。
それを確かめるために プログラム【1】 の strlen関数内に
cout << "こっちだよ!/n";
という行を加えてみました。
// プログラム【3】
#include <cstddef>
#include <iostream>
using namespace std;
size_t strlen(const char* s)
{
size_t len = 0;
cout << "こっちだよ!\n";
while (*s++)
len++;
return len;
}
int main()
{
char s[255];
cout << "文字列を入力 : "; cin >> s;
cout << "文字列\"" << s << "\"の長さ … " << strlen(s) << '\n';
}
コンパイルは無事に成功しました。ですが、実行してみたところ・・・
プログラム【3】で加えた
cout << "こっちだよ!/n";
には、文法上のミスはないので、二つのstrlen関数が競合してしまったのでしょうか。
それを確かめるため、こんどは、strlen関数の名前を srtlen2 に変更してみました。それ以外は一切変更していません。
// プログラム【4】
#include <cstddef>
#include <iostream>
using namespace std;
size_t strlen2(const char* s)
{
size_t len = 0;
cout << "こっちだよ!\n";
while (*s++)
len++;
return len;
}
int main()
{
char s[255];
cout << "文字列を入力 : "; cin >> s;
cout << "文字列\"" << s << "\"の長さ … " << strlen2(s) << '\n';
}
strlen2関数はちゃんと働きました。
以上のことから、プログラム【3】では、二つの strlen関数が競合していることがはっきりしました。
では、なぜプログラム【1】のときは、競合せずに動作したのでしょうか。
プログラム【1】とプログラム【3】の違いは、
cout << "こっちだよ!/n";
の有無だけです。
ここから先は、あくまでも想像ですが・・・
プログラム【1】では、「ライブラリ関数strlen」 と「プログラムに記述したstrlen関数」 は、外から見て全く同じ動作をします。
一方、プログラム【3】では、「プログラムに記述したstrlen関数」が、「こっちだよ!」というメッセージを出力するので、二つのstrlen関数の動作が異なります。
それが、【1】が許されて【3】が許されない理由ではないでしょうか。
引数も返却値も同じなので、多重定義は許されないはずですが、「働きも同じなら、まあいいか」ということですかね。
長くなってしまったので、コードは書きませんが、
プログラム【1】のときに、「ライブラリ関数strlen」 と「プログラムに記述したstrlen関数」の どちらが使われたのかを調べてみました。
外から見た動作を変えるとプログラムが停止してしまうため、入出力のコードを書き加えることはできません。
なので、「プログラムに記述したstrlen関数」の中に for文で時間稼ぎのコードを入れてみたところ、プログラム【1】の動作が極端に遅くなりました。
プログラム【1】では、「ライブラリ関数strlen」ではなく、「プログラムに記述したstrlen関数」が使われたようです。
--
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/6754259
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック