文字と文字列
案外ベテランになっても、各プログラム言語の用意している変数の「型」はすでに用意されているという以上も以下もなく、あまり深く考えていなかった…というケースが多々見受けられます。
たとえばタイトルにもあるように「文字」と「文字列」の違いについて考えてみましょう。
「文字」とは計算できる数値と異なる値およびその1字を指します。
C言語では、char 型(文字型:char は character の略)というデータ型になります。これは1バイトのメモリサイズを持つデータ型で、コンピュータのメモリアクセスは1バイトが最小の単位ですから、char 型は最小のメモリサイズを持つ型であると言えます。
若干気を付けるのは、同じ数の値であっても
計算できる値は「数値」
計算できない値は「数字(数をあらわす文字)」
という点です。
プログラムの世界に足を踏み入れた直後のエンジニアやプログラマはここでなんとなく感覚的には使えていても、理解が伴っていない…ということがよくあります。
たとえば、
int a = 1; // 数値は囲まないのが特徴。大抵ほかの言語でも同じ。
これは数値です。
計算につかえます。
しかし
char b = '1'; // 文字はシングルクォーテーションで囲むのが特徴。
これは文字です。
計算はできません。
「あ」とか「n」といったように、「1」と言う"字"であること以外の意味を持ちません。こういう値そのものを「リテラル」とも言います。この場合は"文字リテラル(文字値)"と呼ぶわけです。
ここまではある程度経験を積むころには嫌でも理解していることでしょう。
一方で「文字列」とは、正式には"文字配列"と言います。
それ自体が文字とは異なる型を持っているのではなく、ただの文字型の配列をあたかも「文字列」という固有の型が別に存在しているかのように定義しているというのが正しい認識です。それでもわざわざ文字の配列のまま取り扱うのではなく、私たち人間が取り扱う際には別の型であるかのように取り扱うのはそうした方がわかりやすく、混乱を避けやすいという側面があるのですから、別に何も問題はないと思います。
結果、昔の人が文字列や文字列リテラルと呼ぶようになって普及しましたが、要するにただの文字を配列で管理しているわけですが、そのせいで文字と文字列はまったく扱いの異なる型だと誤解を与えてしまっているのが現状です。
C言語の場合、文字列の扱いでは一般的に
文末には必ずヌル文字”\0”を加える
必要があります。これはC言語の制約事項の1つで、ヌル文字=リテラルの終端を指すと思っておいてください。この終端を明示しなければ、どこまでが値の範囲なのか特定できません。また、ヌル文字も1文字として計上されますので、反復などを行いながら1文字ずつ抽出する場合は注意が必要です。
面倒なのは、関数や書式によって自動的にヌル文字をつけてくれたり、プログラマが自分でつけなければならなかったりと、プログラム言語としての一貫性がないことでしょうか。
これはC言語が生まれ、改訂されてきた歴史にも関係してきます。
都度、利用者たちのさまざまなフィードバックを反映させ続けた結果、非常に自由度が高く、使いこなせばかなり高度なことも可能な言語となったのと同時にかなり統一感がなく、慣れるまではとても混乱を生み出しやすい言語となりました。
また、C言語の文法をベースにして開発されたJava言語には、文字列だけで
String
StringBuffer
StringBuilder
StringJoiner etc....
と何のためにそんなに作ったんだかよくわからない文字列型がたくさん出てきます。
(いや、それぞれ意味と使いどころやメリデメなどはあるんですけど)
ちなみに、Java言語もベースの文法コンセプトの多くをC言語から取り入れているためか、初期から用意されていた String 型はC言語と同じく文字の配列になっています。
このあたりはどのプログラム言語でもそうですが、あらかじめ用意されている標準関数や型定義などの中身を深く読み取りに行ってみれば自ずとわかります。
そしてその構成を正しく把握すれば、
「どのような処理では、どれほど性能が劣化するのか」
「どのように使うことが最適な型なのか」
なども理解できるようになり、使いどころなどで悩むことも素人じみた効率の悪いプログラムにするリスクもグッと少なくなることでしょう。
いただいたサポートは、全額本noteへの執筆…記載活動、およびそのための情報収集活動に使わせていただきます。