文字リテラルと文字列リテラルと配列
$ 'c'
これは文字リテラル(char)で、ACIIコードで 16進数(hexdecimal)の場合 \x63、8進数(octal)であれば、 \143、10進数であれば、99と表現される。 asciiでは、charのサイズは、1バイト(8ビット)だけど、7ビット(0 - 127)しか使われていない
code: sample
int main(void)
{
char hex_c = '\x63';
char oct_c = '\143';
char dec_c = 99;
fprintf(stdout, "16進数: \n");
write(1, &hex_c, 1);
write(1, "\n", 1);
fprintf(stdout, "8進数: \n");
write(1, &oct_c, 1);
write(1, "\n", 1);
fprintf(stdout, "10進数: \n");
write(1, &dec_c, 1);
write(1, "\n", 1);
return (0);
}
code: result
16進数:
c
8進数:
c
10進数:
c
single quoteのcharacterとint
char hoge = 'c'と char hoge = 99は同じということは、どういうことなのか?
おそらく表記方法が違うだけ
$ "abcdef"
これは文字列リテラルで、メモリ上の書き込み不可領域に格納される。
これを変数に格納する方法はいくつか存在する
文字列リテラルの先頭のアドレスだけ保持しておく方法
code: sample
int main(void)
{
char *fuga = "abcdef";
write(1, fuga, 7);
return (0);
}
code: result
abcdef%
このケースでは、"abcdef"はメモリ上の書き込み領域に格納されるため、書き換えができない
const char* fugaの省略系である
なので、例えば、write(1, &fuga[0], 1); のような形で読み取りはできるが
fuga[0] = 'c' などとすると実行時エラーが起きる。
なので、変更したい場合下記のように配列として受ける必要がある。
配列として初期化する方法
code: sample
int main(void)
{
// 以下の表記はすべて同じ。(シンタックスシュガー)
//char hoge[] = "abcdef";
//char hoge7 = {'a', 'b', 'c', 'd', 'e', 'f', '\0'}; //char hoge[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
write(1, &hoge, 6);
return (0);
}
code: result
abcdef%
ちなみにASCIIで文字列に含めたい場合は以下のようにする
octalで、"\060\141"
$ > 0a
hexで、"\x41\x2f"
$ > A/
配列について
char hoge[3] = {'a', 'b', 'c'};
などと宣言した場合
hoge[0]はchar
hoge[1]も当然char
hogeは char*
それぞれのアドレスを取得するには
&hoge[0]、&hoge[1]などとする
ちなみにhoge[1]というのは*(hoge +1)と完全に同値であり 1[hoge]と書くこともできる
char *hoge[3]は char*を3つ格納できる配列の宣言である。
関数の配列渡し
code: main.c
void with_array_ptr(char *arr)
{
write(1, arr, 3);
}
void with_array(char arr[])
{
write(1, arr, 3);
}
int main(void)
{
char arr3 = {'a', 'b', 'c'}; with_array_ptr(arr);
write(1, "\n", 1);
with_array(arr);
return (0);
}
この場合、char *arrも char arr[]も同じだが、後者の書き方のほうが配列を渡しているというのが明示的でわかりやすい