わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

文字と文字列

朝起きて書いてみました.しかしこれは,何度も手入れしないといけないな….

  • 1バイトの情報を表すためのデータ型は,charです.
    • charと書いたら,signed charなのかunsigned charなのか規定されませんが,利用上は問題ありません.
    • Cのプログラミング教育において,「charは1文字を表すためのデータ型」と言われますし,私も授業ではそう教えていますが,「あ」という文字は1バイトで表現できないことを忘れないようにしたいものです.(関連用語としては「文字コード」と「マルチバイト文字」なのですが,今回は用語の紹介にとどめます.)
  • 'a' で表記する値は「文字定数」と呼ばれます.「文字リテラル」と呼ばれることもあります.
    • シングルクオートの間に書けるのは,1バイトの情報のみです.なので 'abc' は不可です(PerlRubyなどでは 'abc' と書けますが,これは文字列として扱われます).'' もダメです.
    • '\0' や '\141' と書くのは問題ありません.「\0」や「\141」が1バイトの値になるからです.
    • 文字定数のデータ型は,intです.ただし,値の取り得る範囲は,unsigned charと同じになります.
  • "a" で表記する値は「文字列リテラル」と呼ばれます.「文字列定数」とも呼びます.
    • ダブルクオートの間に書ける文字の長さは,任意です(任意長あるいは可変長といいます).1000文字並べてもかまいませんし,途中に「\0」や「\141」があってもかまいません.それと,"" という表記もできます(空文字列と呼ばれます).
    • 文字列リテラルのデータ型は,char *と考えましょう.
    • 配列と文字列の関係でも書きましたが,文字配列の初期値に「char a[] = "Oresama";」と書くことができます.このときは,配列変数aは文字列リテラルを参照しているのではなく,この配列変数の初期値が{'O', 'r', 'e', 's', 'a', 'm', 'a', '\0'}であるという意味になります.
  • 「char a[10];」と配列変数を定義してから,「a[0] = 'X';」のように代入したとします.a[0] はchar型,'X' はint型なので,暗黙の型変換が起こり,'X' は char型に変換されて,a[0]に格納されます.
    • charがunsigned charと同じなら,文字定数の取り得る範囲はunsigned charなので,問題なく代入できます.
    • charがsigned charと同じなら,代入において値が変わる可能性があります.ただし,Cの(初学者向けの)プログラミングで出てくる値は,7ビットで表現されるASCIIコードの値です.ということで 'X' の代入であれば,値が変わるということはありません.
    • charがsigned charであり,かつ「a[0] = '\377';」なら,どうでしょうか.255 を signed charに変換した上でa[0]に代入します.これも「たいていの処理系で」という条件がつきますが,int型の値の下位8ビットが格納されます.ということで,a[0]の値は-1になります.intからcharへの型変換によって,メモリやレジスタの中の「ビット表現」は変わることなく,その値の意味が,変数のデータ型によって変わる,と考えるといいでしょう.
  • isalphaなどの,文字種を判定するライブラリ関数は,引数の型がcharではなくintです.
    • オンラインマニュアルによると,型としてはintですが,値の範囲としてはunsigned charの範囲,またはEOFです.EOFはたいていの処理系で-1と定義されている定数です.
    • 通常,判定の対象となる文字は,ASCIIコードの範囲内ですので,charがsigned charであるような処理系であっても,問題ありません.
  • まとめ.
    • 1文字(1バイト)の値はchar型で表現できますが,しばしばint型に拡張されます.1文字(1バイト)の値がunsigned char型の範囲に収まっている限り,charとintの暗黙の型変換は気にしなくてかまいません.
    • charがunsigned charであっても,signed charであっても,ASCIIコードの中の文字であれば*1,常に非負整数であり,負の値になることはありません.

*1:1バイトが8ビット以上であるという条件も要請されます.もちろん現在動作するほぼすべての処理系が,この条件を満たします.どうしても気になるなら,"#include " とした上で,1バイトが何ビットであるかを表す定数 CHAR_BIT の値を調べましょう.