charを2バイトにするのは実験。普通なら wchar_tを使うべきでしょう。
早速何が起きているか確認。
$ cat literalTest.c
/* 15.Jul.2012 kei */
#include <stdio.h>
#include <stdlib.h>
#include "redefines.h"
int main() {
char a = 'あ';
printf("%x\n", a);
return EXIT_SUCCESS;
}
$ cc -o literalTest literalTest.c
literalTest.c: In function ‘main’:
literalTest.c:8:11: warning: multi-character character constant [-Wmultichar]
literalTest.c:8:2: warning: large integer implicitly truncated to unsigned type
[-Woverflow]
$ ./literalTest
8182
$
実行はできた。でも
$ echo あ | od -tx1
0000000 e3 81 82 0a
0000004
$
だから、e3が掛けているのが判る。
UTF-8は Unicodeの交換用外部フォーマットなので 3バイト。ならば、内部表現の UCS2を使ったらどうか。
$ cc -fexec-charset=ucs2 -o literalTest literalTest.c
literalTest.c: In function ‘main’:
literalTest.c:8:11: warning: multi-character character constant [-Wmultichar]
literalTest.c:8:2: warning: large integer implicitly truncated to unsigned type
[-Woverflow]
literalTest.c:14:0: internal compiler error: character 0xa is not unibyte in
execution character set
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
$
おお今度は警告だけでは済まなかった。 gccの組み込み printfがエラーになったのかも。通常のライブラリ関数にしてみる。
$ cc -fno-builtin-printf -fexec-charset=ucs2 -o literalTest literalTest.c
literalTest.c: In function ‘main’:
literalTest.c:8:11: warning: multi-character character constant [-Wmultichar]
literalTest.c:8:2: warning: large integer implicitly truncated to unsigned type
[-Woverflow]
$ ./literalTest
��$
今度は実行までできたが、出力は文字化け。 UTF-8な環境で UCS2を吐き出したのだから当たり前か。
とりあえず確認用に 16進ダンプを書いてみる。
$ cat literalTest.c
/* 15.Jul.2012 kei */
#include <stdio.h>
#include <stdlib.h>
#include "redefines.h"
void lineFeed() {
byte b = (byte)0xa;
write(fileno(stdout), &b, 1);
}
void dumpDigit(int d) {
byte b = (byte)((d < 10) ? (d + 0x30) : (d + 0x61));
write(fileno(stdout), &b, 1);
}
void dumpByte(int c) {
int d1 = (c >> 4) & 0xf;
int d2 = c & 0xf;
dumpDigit(d1);
dumpDigit(d2);
}
void dump(char c) {
int c1 = c >> 8;
int c2 = c & 0xff;
dumpByte(c1);
dumpByte(c2);
lineFeed();
}
int main() {
char a = 'あ';
dump(a);
return EXIT_SUCCESS;
}
$ cc -fno-builtin-printf -fexec-charset=ucs2 -o literalTest literalTest.c
literalTest.c: In function ‘main’:
literalTest.c:35:11: warning: multi-character character constant [-Wmultichar]
literalTest.c:35:2: warning: large integer implicitly truncated to unsigned type
[-Woverflow]
$ ./literalTest
4230
$
'あ'は UCS2で 0x3042なので、データは大丈夫ようだ。
実例は示さないが、UCS2を使った場合いくつか注意点がある。
ASCIIの範囲でも上位バイトに 0x00が入るため、それなりのprintfでないとすぐに文字列が終端してしまい、なにも表示できない。
wprintfと Lつきのリテラルで英数字を表示することはできるが、漢字などはうまく表示できない。
UCS2な環境にするか、UCS2を扱える printfにするか、printf呼ぶ前に UTF-8に戻す必要があるだろう。
いづれにしても、通常用途ではお勧めできない使い方。
半年で気がついたらぁ
0 件のコメント:
コメントを投稿