表示テーマ
String — 文字列
TL;DR
C文字列は \0(null character)で終わる char の並びです。格納容量には終端の1バイトも必要です。strlen は終端を含まないバイト数を返します。以下の例はISO C99以降です。
Example
snprintf は書き込み容量を指定でき、戻り値で切り詰めを検出できます。
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buffer[16];
const char *name = "C";
int written = snprintf(buffer, sizeof buffer, "Hello, %s", name);
if (written < 0) {
fputs("format error\n", stderr);
return EXIT_FAILURE;
}
if ((size_t)written >= sizeof buffer) {
fputs("buffer too small\n", stderr);
return EXIT_FAILURE;
}
printf("%s (%zu bytes)\n", buffer, strlen(buffer));
return EXIT_SUCCESS;
}Explanation
snprintf の非負の戻り値は、十分な容量があれば書き込まれたはずの長さで、終端を含みません。容量が正なら終端の場所も確保されます。負の戻り値を確認してから size_t に変換します。
| 宣言 | 意味 |
|---|---|
char text[] = "abc"; | 終端込み4要素の変更可能な配列 |
const char *text = "abc"; | 変更しない文字列リテラルへのポインタ |
Pitfalls
NULL終端忘れ
char text[3] = "abc"; は終端を含みません。これを strlen、strcmp、printf の %s に渡して領域外まで読ませると未定義動作です。
- 文字列リテラルを書き換えると未定義動作です。
strncpyは入力が指定長以上なら終端を書きません。単純に「安全なコピー」とは扱えません。strlenは日本語の文字数を数える関数ではありません。sizeofは文字列長ではなく、型やオブジェクトのサイズです。
Related
参考
C11委員会草案 N1570 §6.4.5、§7.21.6.5、§7.24.2.4、§7.24.6.3。