C++ での文字列の sizeof 演算子と strlen 関数の違い
この記事では、C++ の文字列で strlen
関数を使用するのではなく、sizeof
演算子を使用する場合の複数の違いを示します。
sizeof
オペレーターの特性と使用シナリオ
sizeof
演算子は、指定された式またはデータ型のストレージサイズを取得する単項演算子です。この演算子はオブジェクトサイズをバイト単位で評価し、sizeof(char)
は 1
であることが保証されています。
1 バイトは常に 8 ビットに等しいという誤った考えがあり、その結果、オブジェクトのサイズをビット単位で計算できます。実際には、言語自体によって 1 バイトが 8 ビットであるとは保証されていません。これは主に、基盤となるハードウェアプラットフォームに依存します。それでも、最新の汎用ハードウェアのほとんどは 8 ビットバイトを使用しています。
sizeof
演算子は、関数または不完全な型またはビットフィールドを含む式には適用できないことに注意してください。次のサンプルコードでは、sizeof
演算子を異なるタイプの 2つの配列に適用します。結果は、プラットフォームでも同じになる可能性があります。char
のサイズは 1 バイトであることが保証されているため、20 文字の配列は 20 バイトを使用します。
一方、long long
データ型は実装定義であり、この場合、たまたま 8 バイトです。したがって、配列の合計サイズは 160 バイトです。次の例の最後の行に示すように、配列全体の sizeof
を sizeof
の 1つの要素で除算することによって、配列内の要素の数を求めることもできることに注意してください。
#include <iostream>
using std::cout;
using std::endl;
int main() {
char arr[20];
long long arr2[20];
cout << "sizeof ( array of 20 long longs ) : " << sizeof arr << endl;
cout << "sizeof ( array of 20 long longs ) : " << sizeof arr2 << endl;
cout << "length of array of 20 chars) : "
<< ((sizeof arr) / (sizeof arr[0])) << endl;
cout << "length of array of 20 long longs ): "
<< ((sizeof arr2) / (sizeof arr2[0])) << endl;
return EXIT_SUCCESS;
}
出力:
sizeof ( array of 20 long longs ) : 20
sizeof ( array of 20 long longs ) : 160
length of array of 20 chars) : 20
length of array of 20 long longs ): 20
sizeof
演算子を使用して文字列の長さを求めるのは間違っています。C++ の文字列の 2つの表現タイプ、文字列と std::string
クラスについて考えてみましょう。前者は主に char
ポインタを使用してアクセスされ、sizeof
を適用すると、文字列全体ではなく、ポインタ自体のストレージサイズが取得されます。
sizeof
演算子を使用して std::string
オブジェクトのサイズを取得しようとすると、オブジェクトのストレージサイズが取得されます。これは、以下のコードスニペットに示されている文字列の文字数ではありません。
#include <cstring>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
int main() {
const char *text1 = "arbitrary string value 1";
string text2 = "arbitrary string value 2";
cout << "sizeof char* : " << sizeof text1 << endl;
cout << "sizeof string: " << sizeof text2 << endl;
cout << "sizeof string.data: " << sizeof text2.data() << endl;
return EXIT_SUCCESS;
}
出力:
sizeof char* : 8
sizeof string: 32
sizeof string.data: 8
次に、C 文字列ライブラリの残骸である strlen
関数を取得しました。指定された文字列の長さを計算し、関数はバイト数を整数値として返します。strlen
は、有効な文字列が格納されている char
ポインタ、または std::string::c_str
によって返される値に適用できますが、C++ プログラマの選択ではありません。
#include <cstring>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
int main() {
const char *text1 = "arbitrary string value 1";
string text2 = "arbitrary string value 2";
cout << "strlen char* : " << strlen(text1) << endl;
cout << "strlen string: " << strlen(text2.c_str()) << endl;
return EXIT_SUCCESS;
}
出力:
strlen char* : 24
strlen string: 24
std::string::size
メンバー関数を使用して、文字列の文字数を取得する
それどころか、C++ プログラマーは、文字列を処理するためのより安全なメソッドを提供するため、std::string
クラスの size
メンバー関数を利用する必要があります。文字列がある場合は、size
メンバー関数を使用することもできます。新しい string
オブジェクトを作成し、戻り値に対して size
関数を直接呼び出す必要があります。次のコード例は、両方のシナリオの主な使用法を示しています。
#include <cstring>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
int main() {
const char *text1 = "arbitrary string value 1";
string text2 = "arbitrary string value 2";
cout << "length char* : " << string(text1).size() << endl;
cout << "length string: " << text2.size() << endl;
return EXIT_SUCCESS;
}
出力:
length char* : 24
length string: 24