トップ «前の日記(2015-02-01(Sun)) 最新 次の日記(2015-02-03(Tue))» 編集

屑俺日記

僕の備忘録(PC、UN*X、ネットワーク関連が中心)なんです。
自分の書いたところは適当(な時とか)に書き換えますので御了承を。


2015-02-02(Mon) 丸ビルの温度計は摂氏三度

unsigned char から signed_char 色々追試

どうも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や内容が変った場合はあしからず。

index.htmlは ここから。