HOWTO · C
C 言語で char 配列の長さを取得する
この記事では、C 言語で char 配列の長さを取得する方法を示します。
このページの内容
C では、「長さ」が char 配列に確保された要素数を指す場合も、文字列のヌル終端文字より前にある文字数を指す場合もあります。配列型が分かる場所では、配列の記憶域サイズと要素数に sizeof を使います。strlen は、有効なヌル終端文字列に対してのみ使います。
sizeof 演算子で C の char 配列の長さを求める
sizeof array は、C のバイト単位で配列のサイズを返します。これを sizeof array[0] で割ると、要素数が得られます。char 配列では各要素が C の 1 バイトを占めます。ただし、C の 1 バイトは必ずしも 8 ビットのオクテットとは限りません。
次の例を実行します。
このセクションのコードと表示されるラベルや出力は英語のままです。
#include <stdio.h>
int main(void) {
char letters[] = {'C', 'o', 'd', 'e'};
char word[] = "Code";
size_t letters_count = sizeof letters / sizeof letters[0];
size_t word_capacity = sizeof word / sizeof word[0];
size_t word_length = word_capacity - 1;
printf("letters: %zu elements, %zu bytes\n", letters_count, sizeof letters);
printf("word: %zu characters, %zu elements including '\\0'\n",
word_length, word_capacity);
return 0;
}
letters: 4 elements, 4 bytes
word: 4 characters, 5 elements including '\0'
letters の初期化では終端文字のない要素が 4 つ確保されます。文字列リテラルで初期化した word には、見える文字 4 つと終端の \0 を含む 5 要素が入ります。配列に終端文字が含まれると分かっていて、文字列の長さを求める場合に限り、1 を引きます。size_t に対応する printf の変換指定子は %zu です。変更していないコード例のラベルは英語のまま表示されます。
sizeof で配列全体のサイズを測れるのは、配列型がその場で利用できる場合だけです。char text[] のような関数仮引数はポインターに調整されるため、sizeof text が測るのはポインターのサイズです。関数で配列の長さが必要なら、要素数を別に渡してください。サイズに使う符号なし型については、size_tを参照してください。
strlen 関数で C の char 配列の長さを求める
<string.h> で宣言される strlen は、最初の \0 より前にある文字数を数えます。引数は、有効なヌル終端文字列を指していなければなりません。strlen は配列の容量を把握していないため、終端文字のない配列の末尾を安全に見つけることはできません。この表現の仕組みについては、ヌル終端文字列を参照してください。
たとえば、strlen("Code") は 4 を返します。リテラルの配列要素は 5 つありますが、終端文字は数えません。リテラルが終端文字を含むため、この呼び出しは適切です。明示的にサイズを指定した配列に strlen を使うのは、アクセス可能な配列内に終端文字があると分かっている場合に限ってください。
手動カウントで C の char 配列の長さを求める
手動で数える方法は、境界が分かっている場合、または有効な終端文字がある場合に使えます。要素数 count が分かっている配列なら、インデックス 0 から count - 1 までを調べます。array[count] は読み取らないでください。配列に格納された文字列の長さを求める場合は、\0 で停止し、走査が配列の境界を越えないようにします。
この例では、配列の要素数を上限として使い、終端文字でも停止します。text は文字列リテラルで初期化されているため、終端文字は配列内にあります。ループは各要素を読む前に上限を確認するので、text[sizeof text] にアクセスすることはありません。この例は、Code の 4 文字を数えて 4 を表示します。
このセクションのコードと表示されるラベルや出力は英語のままです。
#include <stdio.h>
int main(void) {
char text[] = "Code";
size_t length = 0;
size_t capacity = sizeof text / sizeof text[0];
while (length < capacity && text[length] != '\0') {
++length;
}
printf("%zu\n", length);
return 0;
}
終端文字のないデータでは、別に渡された要素数を使って、その要素だけを処理します。上限内に終端文字があると保証されていない限り、\0 が見つかるまで走査しないでください。
ポインターで C の char 配列の長さを求める
ポインターで文字列をたどることはできますが、配列の容量は保持していません。有効なヌル終端文字列なら、*ptr != '\0' の間ポインターを進められます。この方法にも strlen と同じ終端文字の条件があります。この例では、文字列リテラルから作成した配列のアドレスを使うため、既知の境界内に終端文字があると保証されています。間接参照の前に終端ポインターを確認し、終端文字でも停止します。この例は、Code の 4 文字を数えて 4 を表示します。
このセクションのコードと表示されるラベルや出力は英語のままです。
#include <stdio.h>
int main(void) {
char text[] = "Code";
char *ptr = text;
char *end = text + sizeof text / sizeof text[0];
while (ptr < end && *ptr != '\0') {
++ptr;
}
printf("%zu\n", (size_t)(ptr - text));
return 0;
}
終端文字のないデータでは、別のカウント値または終端ポインターを保持し、既知の境界で停止してください。関数が先頭要素へのポインターを受け取り、文字列の終端文字で長さを表せない配列を走査する必要がある場合は、要素数も引数として渡します。ポインター演算だけでは配列の末尾を判断できません。配列サイズとの関連する違いについては、C の配列の長さを参照してください。
まとめ
目的に合った測定方法を選んでください。配列型全体を利用できる場所では、sizeof array / sizeof array[0] で配列の要素数が得られます。文字列の長さを求める場合に、終端文字を含むと分かっている配列に限り、終端文字の分を差し引きます。有効なヌル終端文字列では、strlen が \0 より前の文字数を数えます。手動走査とポインター走査には、有効な終端文字か明示的な境界が必要です。関数の配列仮引数はポインターになるため、配列を関数に渡すときは長さも保持しておきましょう。