僕の備忘録(PC、UN*X、ネットワーク関連が中心)なんです。
自分の書いたところは適当(な時とか)に書き換えますので御了承を。
どうも32Bitと64Bitの違いみたいだ(
半分間違いとわかった)。
PowerPCのWheezy。
$ uname -a Linux $HOST 3.2.0-4-powerpc #1 Debian 3.2.63-2+deb7u1 ppc GNU/Linux $ gcc -Wall -o sign_unsign sign_unsign.c $ ./sign_unsign | tail -n1 un:254 sn:254 $ file sign_unsign sign_unsign: ELF 32-bit MSB executable, \ PowerPC or cisco 4500, version 1 (SYSV), \ dynamically linked (uses shared libs), \ for GNU/Linux 2.6.26, \ BuildID[sha1]=0xc98da56ac2b1735a277999384c0a2fdc13531bce, \ with unknown capability 0x41000000 = 0x13676e75, \ with unknown capability 0x10000 = 0xb0401, not stripped
amd64のFreeBSD 11-CURRENT。
RasPIでは -Weverything で警告は出なかったはず。
$ uname -a FreeBSD $HOST 11.0-CURRENT FreeBSD 11.0-CURRENT #0 r277524:\ Tue Jan 27 14:03:18 JST 2015 \ root@$HOST:/usr/obj/usr/src/sys/GENERIC amd64 $ cc -Weverything -o sign_unsign sign_unsign.c sign_unsign.c:6:10: warning: implicit conversion changes signedness: 'unsigned char' to 'char' [-Wsign-conversion] ac = uc; ~ ^~ 1 warning generated. $ ./sign_unsign | tail -n1 un:254 sn: -2 $ file sign_unsign sign_unsign: ELF 64-bit LSB executable, x86-64, \ version 1 (FreeBSD), dynamically linked, \ interpreter /libexec/ld-elf.so.1, \ for FreeBSD 11.0 (1100054), not stripped
代入時に型変換してやっても、変りはなかった。
適当に検索して、
ようやく。
charと宣言すると、暗黙にunsigned charになる、処理系があるということ
のようだ(RasbperryPIのFreeBSD及びDebian、PowerPCのDebian)。
32ビットとはいっても、gcc-4.7.2(debian wheezy i686)、
及びclang3.4.1(FreeBSD10.1 i386)
は、charを宣言すると、暗黙にsigned charになっていた。
64BitのFreeBSD/Debian/Ubuntuはいずれもsigned。
いずれにしても宣言時にsinged/unsigned char を指定してやると、ちゃんと。
$ cat sign_unsign3.c #include<stdio.h> int main() { unsigned char uc; signed char ac; for(uc=0; uc<255; uc++){ ac = uc; printf("un:%3d sn:%3d\n", uc,ac); } return 0; } $ ./sign_unsign3 | tail -n1 un:254 sn: -2
ついでに
LSIC-86試食版をWin7(32Bit)でやってみた。
PPCやRaspbianなどと同じ結果になった。
C:\%HOMEPATH%\%lsic330c\BIN> type stest.c #include<stdio.h> #define SIGN_NUM 129 int main() { unsigned char ex_uc = SIGN_NUM; signed char ex_ac = SIGN_NUM; char im_c = SIGN_NUM; printf("unsignd char:%3d\n", ex_uc); printf("signed char:%3d\n", ex_ac); printf("implict char:%3d\n", im_c); return 0; } C:\%HOMEPATH%\%lsic330c\BIN> sign_test.exe unsignd char:129 signed char:-127 implict char:129
ASCII文字は0-127までしかないから、どっちであっても あまり困らなかったのだろうか。
とりあえずは「犬」を選択した。
Ubuntu14.04(x86_64)のgcc-4.8.2および
FreeBSD 11-CURRENT(RaspberryPI)の
clang-3.5.1 で確認。
#include<stdio.h> int main() { char dog[3]; dog[0] = 0xe7 ; dog[1] = 0x8a ; dog[2] = 0xac ; printf("%c%c%c\n", dog[0], dog[1], dog[2]); return 0; } $ ./dog 犬
dog[2]でも gcc -Wallは
エラーメッセージを出さなかったが、clangは不満を鳴らしてきた。
これは-Weverythingがあってもなくても同様。黙らせるに若干の
試行錯誤。
ちなみにdog[3]でもdog[2]でも、
実行結果は(hexdumpに通してみた限りは)全く同じ。
dog[3]にした方のファイルサイズが1バイト大きくなるだけ。
diff dog.c dog2.c 4c4 < unsigned char dog[2]; --- > unsigned char dog[3]; $ ls -l dog dog2 -rwxrwxr-x 1 user group 8511 2月 2 22:07 dog -rwxrwxr-x 1 user group 8512 2月 2 22:07 dog2 [user@freebsd ~]$ ls -l dog dog2 -rwxr-xr-x 1 user wheel 6453 2月 2 22:19 dog -rwxr-xr-x 1 user wheel 6454 2月 2 22:19 dog2
char にsigned をつけたり、= の右に(signed char)を
入れたりしたが、いずれも結果的には不要だった。
また、char を unsigned char にしてもみたが、どちらの
環境でも警告らしいものは出ず、正常に動作した。
リンクはご自由にどうぞ。でもURLや内容が変った場合はあしからず。