char* - 文字列を表現する型
文字列を表現するにはcharのポインタ型である「char*」を使います。
char*
「char*」型には、文字列リテラルを代入できます。
char* name = "Perl";
一般的には、文字列リテラルを代入する場合の用途で「char*」型を使う場合は、const修飾子をつけて、文字の変更を行わないようにしておくのが望ましいです。
const char* name = "Perl";
C言語における文字列とは、末尾が「\0」で終わる文字の配列だということを意識しておきましょう。要素を書くと以下のようになります。
0 1 2 3 4 P e r l \0
意味的には、文字列リテラルの代入は以下のコードと同じになります。
文字列リテラルを代入して出力するサンプルです。
#include <stdio.h> int main(void) { const char* name = "Perl"; printf("%s\n", name); }
実行時に文字列を生成する場合
実行時に動的に文字列を生成するには、mallocでメモリを確保します。Perlという文字は4文字ですが、末尾に「\0」が必要なため、5バイトを確保します。charのサイズは1バイトです。
#include <stdlib.h> char* name = malloc(sizeof(char) * 5); // Perl name[0] = 'P'; name[1] = 'e'; name[2] = 'r'; name[3] = 'l'; name[4] = '\0';
動的に生成した文字列を出力するサンプルです。
#include <stdio.h> #include <stdlib.h> int main(void) { char* name = malloc(sizeof(char) * 5); // Perl name[0] = 'P'; name[1] = 'e'; name[2] = 'r'; name[3] = 'l'; name[4] = '\0'; printf("%s\n", name); }
途中に\0を含む文字列を作成することはできないの?
含むことは可能ですが、文字列に関するC言語関数は、文字列の終わりを「\0」と想定しています。文字列の途中に「\0」を含んだ場合は、その位置を文字列の終了位置として認識します。文字列定数の表現も、末尾に「\0」を自動的につけます。C言語では、文字列の末尾は「\0」であると文法や関数が想定していると考えておくほうがよいでしょう。
C言語の文字列は長さの情報を含んでいないの?
はい。C言語の文字列は長さの情報を含んでいません。「\0」を終了位置とみなしますので、長さを取得する場合は「\0」までの文字数を数える必要があります。文字列の長さを取得するstrlen関数は「\0」までの文字数を数えます。
C言語の文字列のセキュリティリスク
C言語の文字列は末尾が「\0」までを文字列としてみなすという仕様があるために、もし文字列の末尾に「\0」を含むことを忘れると、C言語の文字列関数(最大処理文字数を指定できないもの)は、意図しない位置まで読み込みます。この位置で書き込みを行ってしまうと、バッファオーバーランが発生します。
これは、C言語を記述する場合のメモリ操作で、容易に起こりうることです。
C言語の文字列関数を扱う場合は、意図しない領域まで読み込んでいないか、バッファオーバーランをしないかどうかを、常に考える必要があります。
C言語でなぜ文字列の扱いが難しいのかという理由のひとつが見えてきますね。