Perlテックブログ

ITエンジニアの成長意欲を刺激する技術考察、モジュール開発の日記。Perlイベントや国内や海外のPerlの記事の紹介。

Perlの文字列とC言語の文字列の長さについて

ちょっと最近このことについて考えていた。

C言語の文字列は、終端文字で管理されている

C言語の文字列は、終端文字で管理されている。

const char* string = "abcde";

一見すると、5つだけの文字に見えるが、6文字目に「\0」で表現されるヌル文字が存在する。C言語は、このヌル文字を終端としている。

文字列を表現するためには、6バイト必要ということだ。長さの情報をC言語の文字列は持っていなくって、長さが必要になるたびにstrlen関数で取得するというのがC言語のやり方。

size_t length = strlen(string);

size_t型は、長さを表現する型で、文字列の最大長を格納できる符号なし整数型のエイリアスになっている。とても長い文字列の場合は、そのたびに、終端文字まで見て、長さを取得しないといけないということだね。

それと、文字列の途中で意図せずに「\0」が含まれている場合は、そこで文字列が終わっていると判断してしまう。

Perlの文字列は長さで管理されている

Perlの文字列はというのは、長さで管理されている。文字列の終わりを表現する終端文字というのはなくって、長さで管理されている。

my $string = "abcde";

文字列の途中で「\0」で表現されるヌル文字が入っていても大丈夫。なぜなら、長さで管理されているから。長さが、構造体のフィールドに格納されているから、C言語のように長さを計算する必要がない。

XSにおけるPerlC言語の文字列のやりとり

PerlとCがつながる部分はXSなんだけど、これは、C言語で書かれたAPIが用意されている。

Perl文字列の作成

文字列の作成は次のようにする。newSVpvの第二引数は、文字列の長さで0の場合は、C言語の終端文字までの長さが自動で計算される。

SV* sv_string = sv_2mortal(newSVpv("abced", 5));

newSVpvは、C言語の文字列をPerlの文字列に変換する。長さを明示的に指定することができるし、自動的に計算させることもできる。

C言語文字列の取り出し

文字列の長さを自動的に計算させる場合は、SvPV_nolenを使う。

const char* string = SvPV_nolen(sv_string);

文字列の長さを指定する場合は、SvPVを使う。

const char* string = SvPV(sv_string, 5);

こうやって、うまく対応しているわけだ。すごく考えられて作られているのだなぁ。

SPVMの文字列について

SPVMはPerlC言語をつなぐことを考えていて、昨日の記事では、SPVMの文字列は、const byteにしますと書いた。

でも、このconst byteは、どのように文字列を表現すべきだろうか? 終端文字を「\0」を含むべきだろうか、含まないべきだろうか。

5文字に対して6文字を確保すべきだろうか。それとも、終端文字のことは忘れて、ピッタリ5文字で、長さだけで管理すべきだろうか。

いろいろと思索しているのだけれど、もし5文字ピッタリにした場合は、C言語の標準の文字列ライブラリがすべて使えないということになっちゃう。C言語の文字列関数は、終端文字を前提としている関数がほとんどだから。これが使えないのは痛い。SPVMは文字列関数を独自に実装する予定はないし。

だから、まず最初に、終端が「\0」で終わるようにする文字列実装で、チャレンジしてみようと考えている。文字列関数は「\0」を見つけるか、文字列の終端とみなすという実装にする。文字列関数において、終端が「\0」でない場合は、例外を投げる。

これは、メモリ安全かつ、C言語と親和性があると思う。これでいってみよー。