概要

C言語, C++ 単なるバイト配列。長さの情報がないので終端文字 \x00 が必要
Java UTF-16での16ビットの配列と長さ情報のあるオブジェクト
Scala UTF-16での16ビットの配列と長さ情報のあるオブジェクト
PHP 単なるバイト配列。長さ情報を一応は持っている
Python バイト配列またはUnicodeコードポイントの配列と長さ情報のあるオブジェクト
Ruby バイト配列と長さと文字符号化方式(文字コード)の情報をもったオブジェクト
Perl UTF-8での8ビットの配列または単なるバイト配列と長さ情報のあるオブジェクト

C言語, C++

C言語における文字列は、char型の配列であるか、配列の先頭へのポインタである。

配列自身には長さの情報がないため、文字列にも長さの情報がなく、終端文字として \x00 を置く習慣になっている。

メモリ上に配置された長さよりも長い文字列を保存してしまうと、バッファオーバーフローを起こしてしまう。

マルチバイトの文字はそのまま2バイト以上を使って保存する。文字符号化方式(文字コード)に関する情報は文字列自身は持っていないので、使うごとに文字列がなんの文字コードなのかを意識しないといけない。

ソースコード中に文字列リテラルを書くには、" で囲む。これで \x00 で終わる char[] 型になる。 ' で囲むと文字列ではなく文字(char型)になる。

Java

Javaにおける文字列は、java.lang.Stringクラスのインスタンスで、長さの情報とchar型の配列を持った不変オブジェクトである。長さの情報を持っているため、終端文字を考えなくてよい。

char型は文字列ではなく1文字だけを表すプリミティブ型で2バイトの整数である。

文字符号化方式(文字コード)は常にUTF-16である。Unicodeの \uFFFF より大きい文字はサロゲートペアを使う。サロゲートペアの機能はJava5以降である。

サロゲートペアで表現する文字は4バイト必要なので、char型2つ使って \uFFFF より大きい文字を表現する。従って、char型が単純に単一の文字とは限らず、長さの情報として charの数を返す String#length も実際の文字数と一致するとは限らない。

Javaの最初の頃は、Unicodeは2バイトの範囲に収まっていたので、単一の文字を表すcharは2バイトという仕様だった。あとからそれを拡張する必要に迫られて、charを4バイトに変更するわけにはいかなかったので、 Java5からはサロゲートペアによってchar2つで拡張された文字を表現することになった。

IO処理などの際は、文字符号化方式(文字コード)を指定することで任意の文字コードを扱うことができる。指定を省略した場合のデフォルトの文字符号化方式(文字コード)は環境などによって決められ、最近の環境ではほとんどがUTF-8になる。内部がUTF-16だと意識することはほとんどない。

任意の文字符号化方式のバイナリを外部から読み込んで内部のUTF-16に変換する際には、不正なバイナリは除外してくれる。例えばShift-JISやEUC-JPなどのマルチバイトの符号化の場合で、 2バイト目が2バイト目の範囲でないなどバイト列が不正な部分は、'?' などに置き換えられる。なので、内部で文字列の中に不正なバイナリが混ざってしまう心配をしなくてもよい。

java.lang.String は不変(immutable)であるが、可変(mutable)文字列としては、java.lang.StringBuilder, java.lang.StringBuffer がある。

ソースコード中に文字列リテラル(String型)を書くには、" で囲む。 ' で囲むと文字列ではなく文字(char型)になる。

Scala

Scalaにおける文字列は、Javaのjava.lang.Stringクラスそのままなので、Javaと同じく、内部ではUTF-16で、不変オブジェクトである。

java.lang.Stringscala.Predefscala.collection.immutable.StringOps への暗黙の変換を定義しているので、文字列に対して scala.collection.immutable.StringOps にあるメソッドもそのまま使うことができる。

ソースコード中に文字列リテラル(String型)を書くには、Javaと同じく " で囲む。 ' で囲むと文字列ではなく文字(scala.Char型)になる。

PHP

PHPでは文字列は長さの情報と単なるバイト配列であり、可変である。

長さの情報を持っているため、本来は終端文字を考えなくてよく、文字列の途中に \x00 を含めることもできる。ただし、文字列の途中に \x00 を含めた文字列は、バイナリセーフでない関数に渡すとおかしなことになるかもしれないので、やめたほうがよい。

ソースコード中に文字列リテラルを書くには、 ' または " で囲む。またはヒアドキュメントを使う。

-> 文字列リテラル

文字列リテラルは、ソースコードで使われている文字符号化方式(文字コード)でバイナリに変換されて処理される。

単なるバイト配列であり可変オブジェクトであるので、 C言語のようにインデックスで指定して文字を変更してしまうことが可能。

$str = "abc\n";
echo $str;
// => abc

$str[1] = 'B';
echo $str;
// => aBc

Python

Pythonの文字列は不変オブジェクトで、単なるバイト列とUnicode文字列(Unicodeコードポイントの列)の2種類の文字列がある。

長さの情報を持っているため、終端文字を考えなくてよく、文字列の途中に \x00 を含めることもできる。

Python2ではデフォルトはバイト列になる。u"..." と書くとUnicode文字列になる。

Python3ではデフォルトはUnicode文字列になる。b"..." と書くとバイト列になる。

Python2では、バイト列とUnicode文字列を混ぜて連結しようとすると、バイト列がASCIIの範囲内であればASCIIコードとみなしてUnicodeに変換してから連結する。範囲外のバイトが含まれていれば実行時にエラーになる。

Python3では、2種類を混ぜて連結しようとすると、内容によらずエラーになる。

Unicode文字列はencodeメソッドでバイト列に変換でき、バイト列はdecodeメソッドでUnicode文字列に変換できる。

文字列をリテラルとしてソースコード中に書くには ' または " で囲む。または三重引用符(トリプルクオート) ''' または """ で囲む。

トリプルクオートの中には改行をそのまま含めることもでき、複数行のコメントをトリプルクオートの文字列で書くことがよくある。

-> 文字列リテラル

Ruby

Ruby 1.8以前と1.9以降とでは文字列の扱いが大きく異なる。

1.9以降では、1バイトの整数の配列と長さと文字コードの情報を持ったオブジェクトである。内部の文字コードがUnicodeで統一されているわけではなく、例えば入力・出力ともEUC-JPであれば、内部でもEUC-JPのままにすることで、変換する必要がなくなる。

文字列のencodingメソッドで文字コードを取得できる。また、encodeメソッドで文字コードを変更することができ、そのときバイト列の内容もその文字コードに変換される。 force_encodingメソッドは、文字コードの情報のみを書き換えて、バイト列は書き換えない。

ソースコード中の文字列リテラルは、このソースコードの文字コードと同じ形式でエンコードされた文字列になる。-> マジックコメント

# -*- coding: utf-8 -*-

src = "あいうえお"

p src.encoding
# => #<Encoding:UTF-8>

src = src.encode('EUC-JP')

p src
# => "\x{A4A2}\x{A4A4}\x{A4A6}\x{A4A8}\x{A4AA}"

p src.encoding
# => #<Encoding:EUC-JP>

長さの情報を持っているため、終端文字を考えなくてよく、文字列の途中に \x00 を含めることもできる。ただし、文字列の途中に \x00 を含めた文字列をCで実装された拡張に渡すとおかしなことになるかもしれないので、やめたほうがよい。

文字列のメソッドの中には文字列自身を変更するものがあるため、文字列はmutableなオブジェクトである。これはJavaなどのimmutableな文字列に慣れている人にとってはとても気持ち悪い。

ソースコード中に文字列リテラルを書くには、 ' または " で囲む。またはヒアドキュメントを使う。

-> 文字列リテラル

Perl

Javaに似ていて、内部ではUnicodeで処理していて、外界との入出力時に必要とする文字符号化方式で変換するのが原則。

use Encode qw/decode encode/;

# 入力時(外界が UTF-8 の場合)
$input = decode('utf-8', $input);

# 出力時(外界が UTF-8 の場合)
print encode('utf-8', $str);

または

use Encode qw/decode_utf8 encode_utf8/;

# 入力時(外界が UTF-8 の場合)
$input = decode_utf8($input);

# 出力時(外界が UTF-8 の場合)
print encode_utf8($str);

以下がわかりやすい。

図解: Perl と Unicode 文字列
http://d.hatena.ne.jp/dayflower/20080620/1213925271

Javaと違うのは、内部のUnicodeはPerlではUTF-8になっている点。それから、内部では必ずしもUnicodeである必要はなく、無理やり別の文字符号化方式のバイナリのまま処理し続けることもできる。

UTF-8になっている文字列には文字列オブジェクトにUTF8フラグがついている。そうでない文字列はすべてシングルバイトの文字だとみなされ、 UTF8フラグがオフになっている。外界からの入力時に decode を呼び出せば、UTF8フラグがオンになり、なにも考えなくても文字列として処理できるが、 decode を呼び出さないと、UTF8フラグがオフのままになり、文字符号化方式を常に意識しないといけない。

Perl Unicode の手引き | perldoc.jp
http://perldoc.jp/docs/perl/5.10.0/perluniintro.pod

Perl における Unicode サポート | perldoc.jp
http://perldoc.jp/docs/perl/5.12.1/perlunicode.pod

Encode | search.cpan.org
http://search.cpan.org/dist/Encode/Encode.pm

ソースコード中に文字列リテラルを書くには、 ' または " で囲む。

-> 文字列リテラル

Gauche (Scheme)

Gaucheの文字列は、内部ではUTF-8でバイト列を保持しており、バイト数と文字数の情報も持っている。バイト数の情報があるため内部に終端文字を持っているとは限らず、文字列の途中に \x00 を含めることもできる。文字列はJavaなどと同じく不変であり、文字列を書き換える際にはいったんメモリ上でコピーされる。部分文字列を取得する際には内部でバイト列を共有する。

内部の文字符号化方式(エンコーディング)はGauche自身のコンパイル時のconfigureオプションで UTF-8以外を選択することもできる。

文字列について | Gaushe
http://practical-scheme.net/gauche/memo-str-j.html

sh (シェルスクリプト)

変数に入れる値やコマンドに渡すパラメータなどはすべて文字列で、数値も文字列で表され、区別がない。

JavaScript

ソースコード中に文字列リテラルを書くには、 ' または " で囲む。

CoffeeScript

ソースコード中に文字列リテラルを書くには、 ' または " で囲む。

" で囲んだ文字列は、中に式を埋め込むことができる。

このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。
スポンサーリンク