Skip to content

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"; は終端を含みません。これを strlenstrcmpprintf%s に渡して領域外まで読ませると未定義動作です。

  • 文字列リテラルを書き換えると未定義動作です。
  • strncpy は入力が指定長以上なら終端を書きません。単純に「安全なコピー」とは扱えません。
  • strlen は日本語の文字数を数える関数ではありません。
  • sizeof は文字列長ではなく、型やオブジェクトのサイズです。

参考

C11委員会草案 N1570 §6.4.5、§7.21.6.5、§7.24.2.4、§7.24.6.3。