昔の最近の出来事(2019.06)

2019/06/30

昼前起床。

そういやここ1カ月の間、NVIDIAのドライバアップデートが無かったな?

掃除したり洗濯したり。

大判書籍が本棚に入らなくなってきたり。少しでも隙間を詰めて入れるしか ない立体パズル状態。まだ解は見つからず(^^;

GTS。なかなか取れない。

2019/06/29

AM中に起床。雨が降ってたけどちょろりお出かけ。

ちょろりGTS。勝てねぇ。

何気に観ていた「この音とまれ!」のアニメ。え?終わり?と 思ったら、第2クールは秋放送らしい。元々分割2クールでの放送 予定だったらしいのですが、第2クールの予告くらい入れれば 良いのにとは思ったりも。

2019/06/28

遅めに帰着。

GTSのアップデートが来てたり。今回もスタンバイ中インストールが 出来ていたので待ち時間は無し。いくつか追加されたイベントをやってみる のですが、またなかなか勝てない感じに。加えて獲得CRも少ないのが イマイチ。

ちょろりコーディング。そういやfloor()って、0方向に丸める のかと思っていたのですが違ってたのを今更知ったり。 浮動小数点数で負の値を整数にするのに何気にfloor()を使ったら 思った感じにならなくて気づいたという(^^; 0方向に切り捨てる ならば、単純に整数型にキャストするので良いのかも。

2019/06/27

遅めに帰着。

調べ事をして終了。

2019/06/26

遅めに帰着。

ちょろりコーディング。なんとなく思った感じに。 D言語のstd.BigIntを初めて使ってみました。手軽です。

2019/06/25

遅めに帰着。

ちょろりコーディング。勘違いになかなか気づけず。修行が足りません。

2019/06/24

遅めに帰着。

あまりの眠さに急速停止。

2019/06/23

AM中に起床。

掃除したり洗濯したり。

ちょろりGTS。全く歯が立たない。なんでだ?

ちょろりコーディング。まとまらず。

2019/06/22

AM中に起床。

ちょろりGTS。サン=クロワ・サーキット(オリジナルコース)は いつも鬼門です。

2019/06/21

遅めに帰着。

ちょろりGTS。

2019/06/20

早めに帰着。

あまりの眠さに急速停止。

2019/06/19

遅めに帰着。

Web巡回して終了。

2019/06/18

遅めに帰着。

地震があったようだけど、TVでは津波避難をかなり長い時間 繰り返してましたが、その間の現地情報は全く無い感じ。

2019/06/17

遅めに帰着。

GTS。Gr1の耐久リーグはまた全く歯が立たないぞ?

2019/06/16

AM中に起床。

洗濯したり掃除したり。エアコンのフィルターを掃除して稼働準備完了。

こちらのGNU Emacsの日本語訳 マニュアル(物量がスゴイんですけど!?)を見ていて、perlのデバッグモードを 使えるperldbやTRAMPでリモートマシンのgdbを起動できる事を知ったり。 後者が可能なのは知りませんでした。

リモートマシンのソースファイルを開いて、リモートマシンの実行ファイルを M-x gdb で起動してみたり。ブレークポイントはソースファイルのバッファの行位置に 関連付けられるようですが、ステップ実行しても現在位置を示す印は付かないようだったり。 なので、今のところは term+ などEmacs上のターミナルからsshでリモート マシンにアクセスしてgdbを起動しているのと変わらない感じに思ったりも。

GTS。耐久リーグをちょっとずつ消化。

2019/06/15

起きたら午後もいい時間。寝すぎ。

C言語で整数型のbit幅を越えたシフト演算を行った結果の話。 x86系ではオプティマイズオプションによって結果が変わる事があった のですが、シフト量が実行時に決定される場合はどうなるんだろう? というのを確かめてみたり。Cygwin32のgccでは以下のような感じに。

$ cat -n shift_test2.c
     1  #include <stdio.h>
     2
     3  int main()
     4  {
     5    uint32_t tmp32=0xffffffff ;
     6
     7    for( int i=0 ; i<33 ; i++ ){
     8      printf("shift=%2d left32:%08x  right32:%08x\n",i,tmp32<<i,tmp32>>i) ;
     9    }
    10    return 0 ;
    11  }

$ gcc -O2 shift_test2.c

$ ./a.exe
shift= 0 left32:ffffffff  right32:ffffffff
shift= 1 left32:fffffffe  right32:7fffffff
shift= 2 left32:fffffffc  right32:3fffffff
shift= 3 left32:fffffff8  right32:1fffffff
shift= 4 left32:fffffff0  right32:0fffffff
shift= 5 left32:ffffffe0  right32:07ffffff
shift= 6 left32:ffffffc0  right32:03ffffff
shift= 7 left32:ffffff80  right32:01ffffff
shift= 8 left32:ffffff00  right32:00ffffff
shift= 9 left32:fffffe00  right32:007fffff
shift=10 left32:fffffc00  right32:003fffff
shift=11 left32:fffff800  right32:001fffff
shift=12 left32:fffff000  right32:000fffff
shift=13 left32:ffffe000  right32:0007ffff
shift=14 left32:ffffc000  right32:0003ffff
shift=15 left32:ffff8000  right32:0001ffff
shift=16 left32:ffff0000  right32:0000ffff
shift=17 left32:fffe0000  right32:00007fff
shift=18 left32:fffc0000  right32:00003fff
shift=19 left32:fff80000  right32:00001fff
shift=20 left32:fff00000  right32:00000fff
shift=21 left32:ffe00000  right32:000007ff
shift=22 left32:ffc00000  right32:000003ff
shift=23 left32:ff800000  right32:000001ff
shift=24 left32:ff000000  right32:000000ff
shift=25 left32:fe000000  right32:0000007f
shift=26 left32:fc000000  right32:0000003f
shift=27 left32:f8000000  right32:0000001f
shift=28 left32:f0000000  right32:0000000f
shift=29 left32:e0000000  right32:00000007
shift=30 left32:c0000000  right32:00000003
shift=31 left32:80000000  right32:00000001
shift=32 left32:ffffffff  right32:ffffffff

$ gcc -v
組み込み spec を使用しています。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-cygwin/7.4.0/lto-wrapper.exe
ターゲット: i686-pc-cygwin
configure 設定: /cygdrive/i/szsz/tmpp/gcc/gcc-7.4.0-1.i686/src/gcc-7.4.0/configure --srcdir=/cygdrive/i/szsz/tmpp/gcc/gcc-7.4.0-1.i686/src/gcc-7.4.0 --prefix=/usr --exec-prefix=/usr --localstatedir=/var --sysconfdir=/etc --docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=i686-pc-cygwin --host=i686-pc-cygwin --target=i686-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --libexecdir=/usr/lib --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --enable-__cxa_atexit --with-dwarf2 --with-arch=i686 --with-tune=generic --disable-sjlj-exceptions --enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enable-libcilkrts --enable-libgomp --enable-libitm --enable-libquadmath --enable-libquadmath-support --disable-libssp --enable-libada --disable-symvers --with-gnu-ld --with-gnu-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib --enable-linker-build-id --with-default-libstdcxx-abi=gcc4-compatible --enable-libstdcxx-filesystem-ts
スレッドモデル: posix
gcc バージョン 7.4.0 (GCC)

当然ですがワーニングメッセージは出なくなります。そしてシフト量が 32の場合はシフト量0と同じになり、先日思った 「シフト量がコンパイル時には 決定できず実行時に判る場合、-O2でもシフトされない場合があるんじゃ なかろうか?」 はその通りシフトされない場合はあるようです。

RaspberryPiで確かめた感じは以下の通り。

$ cat -n shift_test2.c
     1  #include <stdio.h>
     2  #include <stdint.h>
     3
     4  int main()
     5  {
     6    uint32_t tmp32=0xffffffff ;
     7
     8    for( int i=0 ; i<33 ; i++ ){
     9      printf("shift=%2d left32:%08x  right32:%08x\n",i,tmp32<<i,tmp32>>i) ;
    10    }
    11    return 0 ;
    12  }

$ /usr/local/arm_linux_gnueabi/bin/arm-linux-gnueabi-gcc -O2 shift_test2.c

$ ./a.out
shift= 0 left32:ffffffff  right32:ffffffff
shift= 1 left32:fffffffe  right32:7fffffff
shift= 2 left32:fffffffc  right32:3fffffff
shift= 3 left32:fffffff8  right32:1fffffff
shift= 4 left32:fffffff0  right32:0fffffff
shift= 5 left32:ffffffe0  right32:07ffffff
shift= 6 left32:ffffffc0  right32:03ffffff
shift= 7 left32:ffffff80  right32:01ffffff
shift= 8 left32:ffffff00  right32:00ffffff
shift= 9 left32:fffffe00  right32:007fffff
shift=10 left32:fffffc00  right32:003fffff
shift=11 left32:fffff800  right32:001fffff
shift=12 left32:fffff000  right32:000fffff
shift=13 left32:ffffe000  right32:0007ffff
shift=14 left32:ffffc000  right32:0003ffff
shift=15 left32:ffff8000  right32:0001ffff
shift=16 left32:ffff0000  right32:0000ffff
shift=17 left32:fffe0000  right32:00007fff
shift=18 left32:fffc0000  right32:00003fff
shift=19 left32:fff80000  right32:00001fff
shift=20 left32:fff00000  right32:00000fff
shift=21 left32:ffe00000  right32:000007ff
shift=22 left32:ffc00000  right32:000003ff
shift=23 left32:ff800000  right32:000001ff
shift=24 left32:ff000000  right32:000000ff
shift=25 left32:fe000000  right32:0000007f
shift=26 left32:fc000000  right32:0000003f
shift=27 left32:f8000000  right32:0000001f
shift=28 left32:f0000000  right32:0000000f
shift=29 left32:e0000000  right32:00000007
shift=30 left32:c0000000  right32:00000003
shift=31 left32:80000000  right32:00000001
shift=32 left32:00000000  right32:00000000

$ /usr/local/arm_linux_gnueabi/bin/arm-linux-gnueabi-gcc -v
Using built-in specs.
COLLECT_GCC=/usr/local/arm_linux_gnueabi/bin/arm-linux-gnueabi-gcc
COLLECT_LTO_WRAPPER=/usr/local/arm_linux_gnueabi/libexec/gcc/arm-linux-gnueabi/8.2.0/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../gcc-8.2.0/configure --with-pkgversion='gcc-8 b201abfd00' --enable-languages=c --prefix=/usr/local/arm_linux_gnueabi --target=arm-linux-gnueabi --with-arch=armv6 --disable-libsanitizer --disable-nls --disable-bootstrap --disable-multilib
Thread model: posix
gcc version 8.2.0 (gcc-8 b201abfd00)

こちらは命令セットの都合により32bitのシフトは0になるようです。

となると、ビット幅を越えたシフトをしようとするとエラーになったD言語では どうなるか?と思う訳ですが結果は以下の通り。

$ cat -n shift_test2.d
     1  import std.stdio;
     2
     3  int main()
     4  {
     5    uint  tmp32=0xffffffff ;
     6
     7    for( int i=0 ; i<33 ; i++ ){
     8      writef("shift=%2d left32:%08x  right32:%08x\n",i,tmp32<<i,tmp32>>i) ;
     9    }
    10    return 0 ;
    11  }

$ dmd -O shift_test2.d

$ ./shift_test2.exe
shift= 0 left32:ffffffff  right32:ffffffff
shift= 1 left32:fffffffe  right32:7fffffff
shift= 2 left32:fffffffc  right32:3fffffff
shift= 3 left32:fffffff8  right32:1fffffff
shift= 4 left32:fffffff0  right32:0fffffff
shift= 5 left32:ffffffe0  right32:07ffffff
shift= 6 left32:ffffffc0  right32:03ffffff
shift= 7 left32:ffffff80  right32:01ffffff
shift= 8 left32:ffffff00  right32:00ffffff
shift= 9 left32:fffffe00  right32:007fffff
shift=10 left32:fffffc00  right32:003fffff
shift=11 left32:fffff800  right32:001fffff
shift=12 left32:fffff000  right32:000fffff
shift=13 left32:ffffe000  right32:0007ffff
shift=14 left32:ffffc000  right32:0003ffff
shift=15 left32:ffff8000  right32:0001ffff
shift=16 left32:ffff0000  right32:0000ffff
shift=17 left32:fffe0000  right32:00007fff
shift=18 left32:fffc0000  right32:00003fff
shift=19 left32:fff80000  right32:00001fff
shift=20 left32:fff00000  right32:00000fff
shift=21 left32:ffe00000  right32:000007ff
shift=22 left32:ffc00000  right32:000003ff
shift=23 left32:ff800000  right32:000001ff
shift=24 left32:ff000000  right32:000000ff
shift=25 left32:fe000000  right32:0000007f
shift=26 left32:fc000000  right32:0000003f
shift=27 left32:f8000000  right32:0000001f
shift=28 left32:f0000000  right32:0000000f
shift=29 left32:e0000000  right32:00000007
shift=30 left32:c0000000  right32:00000003
shift=31 left32:80000000  right32:00000001
shift=32 left32:ffffffff  right32:ffffffff

$ dmd --version
DMD32 D Compiler v2.085.0

Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved written by Walter Bright


コンパイル時のチェックは不可能になり、C言語+gccと同じく32bitのシフト ではシフト量0となるようです。

x86でもuint64_tでシフトしておいて最後にuint32_tにキャストすれば32bit以上 (ただし63bit以下)のシフトも可能なのでは?と思い試してみたところ、少し 不思議な結果になったり。以下はFedoraのgccで試した結果。

$ cat -n shift_test3.c
     1  #include <stdio.h>
     2  #include <stdint.h>
     3
     4  int main()
     5  {
     6    uint64_t tmp64=0xffffffff ;
     7
     8    for( int i=0 ; i<33 ; i++ ){
     9      printf("shift=%2d left32:%08x  right32:%08x\n",i,tmp64<<i,tmp64>>i) ;
    10    }
    11    return 0 ;
    12  }

$ gcc -O2 -m64 shift_test3.c

$ ./a.out
shift= 0 left32:ffffffff  right32:ffffffff
shift= 1 left32:fffffffe  right32:7fffffff
shift= 2 left32:fffffffc  right32:3fffffff
shift= 3 left32:fffffff8  right32:1fffffff
shift= 4 left32:fffffff0  right32:0fffffff
shift= 5 left32:ffffffe0  right32:07ffffff
shift= 6 left32:ffffffc0  right32:03ffffff
shift= 7 left32:ffffff80  right32:01ffffff
shift= 8 left32:ffffff00  right32:00ffffff
shift= 9 left32:fffffe00  right32:007fffff
shift=10 left32:fffffc00  right32:003fffff
shift=11 left32:fffff800  right32:001fffff
shift=12 left32:fffff000  right32:000fffff
shift=13 left32:ffffe000  right32:0007ffff
shift=14 left32:ffffc000  right32:0003ffff
shift=15 left32:ffff8000  right32:0001ffff
shift=16 left32:ffff0000  right32:0000ffff
shift=17 left32:fffe0000  right32:00007fff
shift=18 left32:fffc0000  right32:00003fff
shift=19 left32:fff80000  right32:00001fff
shift=20 left32:fff00000  right32:00000fff
shift=21 left32:ffe00000  right32:000007ff
shift=22 left32:ffc00000  right32:000003ff
shift=23 left32:ff800000  right32:000001ff
shift=24 left32:ff000000  right32:000000ff
shift=25 left32:fe000000  right32:0000007f
shift=26 left32:fc000000  right32:0000003f
shift=27 left32:f8000000  right32:0000001f
shift=28 left32:f0000000  right32:0000000f
shift=29 left32:e0000000  right32:00000007
shift=30 left32:c0000000  right32:00000003
shift=31 left32:80000000  right32:00000001
shift=32 left32:00000000  right32:00000000

$ gcc -O2 -m32 shift_test3.c

$ ./a.out
shift= 0 left32:ffffffff  right32:00000000
shift= 1 left32:fffffffe  right32:00000001
shift= 2 left32:fffffffc  right32:00000003
shift= 3 left32:fffffff8  right32:00000007
shift= 4 left32:fffffff0  right32:0000000f
shift= 5 left32:ffffffe0  right32:0000001f
shift= 6 left32:ffffffc0  right32:0000003f
shift= 7 left32:ffffff80  right32:0000007f
shift= 8 left32:ffffff00  right32:000000ff
shift= 9 left32:fffffe00  right32:000001ff
shift=10 left32:fffffc00  right32:000003ff
shift=11 left32:fffff800  right32:000007ff
shift=12 left32:fffff000  right32:00000fff
shift=13 left32:ffffe000  right32:00001fff
shift=14 left32:ffffc000  right32:00003fff
shift=15 left32:ffff8000  right32:00007fff
shift=16 left32:ffff0000  right32:0000ffff
shift=17 left32:fffe0000  right32:0001ffff
shift=18 left32:fffc0000  right32:0003ffff
shift=19 left32:fff80000  right32:0007ffff
shift=20 left32:fff00000  right32:000fffff
shift=21 left32:ffe00000  right32:001fffff
shift=22 left32:ffc00000  right32:003fffff
shift=23 left32:ff800000  right32:007fffff
shift=24 left32:ff000000  right32:00ffffff
shift=25 left32:fe000000  right32:01ffffff
shift=26 left32:fc000000  right32:03ffffff
shift=27 left32:f8000000  right32:07ffffff
shift=28 left32:f0000000  right32:0fffffff
shift=29 left32:e0000000  right32:1fffffff
shift=30 left32:c0000000  right32:3fffffff
shift=31 left32:80000000  right32:7fffffff
shift=32 left32:00000000  right32:ffffffff

$ gcc -v
組み込み spec を使用しています。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
ターゲット: x86_64-redhat-linux
configure 設定: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
スレッドモデル: posix
gcc バージョン 9.1.1 20190503 (Red Hat 9.1.1-1) (GCC)

んんん??? -m64の方は32bitのシフト結果が0となる想定された結果が 得られたのですが、-m32の方が なんだこれ? って結果になったり。 なんとなくprintf()の問題っぽい気がしたので以下のように直してみたところ、 一応想定通りの結果が得られるようだったり。

$ cat -n shift_test4.c
     1  #include <stdio.h>
     2  #include <stdint.h>
     3
     4  int main()
     5  {
     6    uint64_t tmp64=0xffffffff ;
     7
     8    for( int i=0 ; i<33 ; i++ ){
     9      printf("shift=%2d left32:%08x  right32:%08x\n",i,(uint32_t)((tmp64<<i)&0xffffffff),(uint32_t)((tmp64>>i)&0xffffffff)) ;
    10    }
    11    return 0 ;
    12  }

$ gcc -O2 -m64 shift_test4.c

$ ./a.out
shift= 0 left32:ffffffff  right32:ffffffff
shift= 1 left32:fffffffe  right32:7fffffff
shift= 2 left32:fffffffc  right32:3fffffff
shift= 3 left32:fffffff8  right32:1fffffff
shift= 4 left32:fffffff0  right32:0fffffff
shift= 5 left32:ffffffe0  right32:07ffffff
shift= 6 left32:ffffffc0  right32:03ffffff
shift= 7 left32:ffffff80  right32:01ffffff
shift= 8 left32:ffffff00  right32:00ffffff
shift= 9 left32:fffffe00  right32:007fffff
shift=10 left32:fffffc00  right32:003fffff
shift=11 left32:fffff800  right32:001fffff
shift=12 left32:fffff000  right32:000fffff
shift=13 left32:ffffe000  right32:0007ffff
shift=14 left32:ffffc000  right32:0003ffff
shift=15 left32:ffff8000  right32:0001ffff
shift=16 left32:ffff0000  right32:0000ffff
shift=17 left32:fffe0000  right32:00007fff
shift=18 left32:fffc0000  right32:00003fff
shift=19 left32:fff80000  right32:00001fff
shift=20 left32:fff00000  right32:00000fff
shift=21 left32:ffe00000  right32:000007ff
shift=22 left32:ffc00000  right32:000003ff
shift=23 left32:ff800000  right32:000001ff
shift=24 left32:ff000000  right32:000000ff
shift=25 left32:fe000000  right32:0000007f
shift=26 left32:fc000000  right32:0000003f
shift=27 left32:f8000000  right32:0000001f
shift=28 left32:f0000000  right32:0000000f
shift=29 left32:e0000000  right32:00000007
shift=30 left32:c0000000  right32:00000003
shift=31 left32:80000000  right32:00000001
shift=32 left32:00000000  right32:00000000

$ gcc -O2 -m32 shift_test4.c

$ ./a.out
shift= 0 left32:ffffffff  right32:ffffffff
shift= 1 left32:fffffffe  right32:7fffffff
shift= 2 left32:fffffffc  right32:3fffffff
shift= 3 left32:fffffff8  right32:1fffffff
shift= 4 left32:fffffff0  right32:0fffffff
shift= 5 left32:ffffffe0  right32:07ffffff
shift= 6 left32:ffffffc0  right32:03ffffff
shift= 7 left32:ffffff80  right32:01ffffff
shift= 8 left32:ffffff00  right32:00ffffff
shift= 9 left32:fffffe00  right32:007fffff
shift=10 left32:fffffc00  right32:003fffff
shift=11 left32:fffff800  right32:001fffff
shift=12 left32:fffff000  right32:000fffff
shift=13 left32:ffffe000  right32:0007ffff
shift=14 left32:ffffc000  right32:0003ffff
shift=15 left32:ffff8000  right32:0001ffff
shift=16 left32:ffff0000  right32:0000ffff
shift=17 left32:fffe0000  right32:00007fff
shift=18 left32:fffc0000  right32:00003fff
shift=19 left32:fff80000  right32:00001fff
shift=20 left32:fff00000  right32:00000fff
shift=21 left32:ffe00000  right32:000007ff
shift=22 left32:ffc00000  right32:000003ff
shift=23 left32:ff800000  right32:000001ff
shift=24 left32:ff000000  right32:000000ff
shift=25 left32:fe000000  right32:0000007f
shift=26 left32:fc000000  right32:0000003f
shift=27 left32:f8000000  right32:0000001f
shift=28 left32:f0000000  right32:0000000f
shift=29 left32:e0000000  right32:00000007
shift=30 left32:c0000000  right32:00000003
shift=31 left32:80000000  right32:00000001
shift=32 left32:00000000  right32:00000000

$ gcc -v
組み込み spec を使用しています。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
ターゲット: x86_64-redhat-linux
configure 設定: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
スレッドモデル: posix
gcc バージョン 9.1.1 20190503 (Red Hat 9.1.1-1) (GCC)
printf()で渡される所で自動的にキャストされると思っていたのですが 明示的にキャストしないとダメみたい。-m32と-m64とで違いが出るとは。 なんかハマりどころしかありません(^^;

そういやCygwinのgccって、stdint.hをインクルードしなくても uint*_tを使えるようになってる模様。気付かずCygwinでコンパイル できたものを他に持って行ったら「そんな型知らん」と怒られて 気づきました。

ちょろりGTS。

2019/06/14

早めに帰着。

自転車のブレーキワイヤーが切れてしまったので近所の自転車屋で修理。 明日でもいいか?と一瞬思ったのですが、雨が降るというのを 思い出し、直すなら今だと思った次第。

2019/06/13

遅めに帰着。

C言語で整数型のbit幅を越えたシフト演算を行った時の結果が、 オプティマイズオプションなどに依存して変わるというのを知ったり。

$ cat -n shift_test.c
     1  #include <stdio.h>
     2
     3  int main()
     4  {
     5    uint32_t tmp32=0xffffffff ;
     6    uint64_t tmp64=0xa0000000ffffffff ;
     7    printf("left32:%08x\n",tmp32<<32) ;
     8    printf("left64:%016llx\n",tmp64<<64) ;
     9    printf("right32:%08x\n",tmp32>>32) ;
    10    printf("right64:%016llx\n",tmp64>>64) ;
    11    return 0 ;
    12  }

$ gcc -v
組み込み spec を使用しています。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-cygwin/7.4.0/lto-wrapper.exe
ターゲット: i686-pc-cygwin
configure 設定: /cygdrive/i/szsz/tmpp/gcc/gcc-7.4.0-1.i686/src/gcc-7.4.0/configure --srcdir=/cygdrive/i/szsz/tmpp/gcc/gcc-7.4.0-1.i686/src/gcc-7.4.0 --prefix=/usr --exec-prefix=/usr --localstatedir=/var --sysconfdir=/etc --docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C --build=i686-pc-cygwin --host=i686-pc-cygwin --target=i686-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --libexecdir=/usr/lib --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --enable-__cxa_atexit --with-dwarf2 --with-arch=i686 --with-tune=generic --disable-sjlj-exceptions --enable-languages=ada,c,c++,fortran,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enable-libcilkrts --enable-libgomp --enable-libitm --enable-libquadmath --enable-libquadmath-support --disable-libssp --enable-libada --disable-symvers --with-gnu-ld --with-gnu-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-prefix --without-libintl-prefix --with-system-zlib --enable-linker-build-id --with-default-libstdcxx-abi=gcc4-compatible --enable-libstdcxx-filesystem-ts
スレッドモデル: posix
gcc バージョン 7.4.0 (GCC)

$ gcc -O0 shift_test.c
shift_test.c: 関数 ‘main’ 内:
shift_test.c:7:31: 警告: 左シフト回数 >= 型の幅となっています [-Wshift-count-overflow]
   printf("left32:%08x\n",tmp32<<32) ;
                               ^~
shift_test.c:8:34: 警告: 左シフト回数 >= 型の幅となっています [-Wshift-count-overflow]
   printf("left64:%016llx\n",tmp64<<64) ;
                                  ^~
shift_test.c:9:32: 警告: 右シフト回数 >= 型の幅となっています [-Wshift-count-overflow]
   printf("right32:%08x\n",tmp32>>32) ;
                                ^~
shift_test.c:10:35: 警告: 右シフト回数 >= 型の幅となっています [-Wshift-count-overflow]
   printf("right64:%016llx\n",tmp64>>64) ;
                                   ^~

$ ./a.exe
left32:ffffffff
left64:a0000000ffffffff
right32:ffffffff
right64:a0000000ffffffff

$ gcc -O2 shift_test.c
shift_test.c: 関数 ‘main’ 内:
shift_test.c:7:31: 警告: 左シフト回数 >= 型の幅となっています [-Wshift-count-overflow]
   printf("left32:%08x\n",tmp32<<32) ;
                               ^~
shift_test.c:8:34: 警告: 左シフト回数 >= 型の幅となっています [-Wshift-count-overflow]
   printf("left64:%016llx\n",tmp64<<64) ;
                                  ^~
shift_test.c:9:32: 警告: 右シフト回数 >= 型の幅となっています [-Wshift-count-overflow]
   printf("right32:%08x\n",tmp32>>32) ;
                                ^~
shift_test.c:10:35: 警告: 右シフト回数 >= 型の幅となっています [-Wshift-count-overflow]
   printf("right64:%016llx\n",tmp64>>64) ;
                                   ^~

$ ./a.exe
left32:00000000
left64:0000000000000000
right32:00000000
right64:0000000000000000

エー? 因みにD言語ではエラーになるようです。

$ cat -n shift_test.d
     1  import std.stdio;
     2
     3  int main()
     4  {
     5    uint  tmp32=0xffffffff ;
     6    ulong tmp64=0xa0000000ffffffff ;
     7    writef("left32:%08x\n",tmp32<<32) ;
     8    writef("left64:%016x\n",tmp64<<64) ;
     9    writef("right32:%08x\n",tmp32>>32) ;
    10    writef("right64:%016x\n",tmp64>>64) ;
    11    return 0 ;
    12  }

$ dmd -O shift_test.d
shift_test.d(7): Error: shift by 32 is outside the range `0..31`
shift_test.d(7): Error: template `std.stdio.writef` cannot deduce function from argument types `!()(string, uint)`, candidates are:
C:\D\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(3952):        `std.stdio.writef(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))`
C:\D\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(3963):        `std.stdio.writef(Char, A...)(in Char[] fmt, A args)`
shift_test.d(8): Error: shift by 64 is outside the range `0..63`
shift_test.d(8): Error: template `std.stdio.writef` cannot deduce function from argument types `!()(string, ulong)`, candidates are:
C:\D\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(3952):        `std.stdio.writef(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))`
C:\D\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(3963):        `std.stdio.writef(Char, A...)(in Char[] fmt, A args)`
shift_test.d(9): Error: shift by 32 is outside the range `0..31`
shift_test.d(9): Error: template `std.stdio.writef` cannot deduce function from argument types `!()(string, uint)`, candidates are:
C:\D\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(3952):        `std.stdio.writef(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))`
C:\D\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(3963):        `std.stdio.writef(Char, A...)(in Char[] fmt, A args)`
shift_test.d(10): Error: shift by 64 is outside the range `0..63`
shift_test.d(10): Error: template `std.stdio.writef` cannot deduce function from argument types `!()(string, ulong)`, candidates are:
C:\D\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(3952):        `std.stdio.writef(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))`
C:\D\dmd2\windows\bin\..\..\src\phobos\std\stdio.d(3963):        `std.stdio.writef(Char, A...)(in Char[] fmt, A args)`

一定の結果が得られないのであれば、D言語のようにエラーにするのは アリかな?とは思ったりも。

RaspberryPiのLinuxとarm-gccで試してみた所、最適化オプションによる結果の 違いは無かったり。

$ cat -n shift_test.c
     1  #include <stdio.h>
     2  #include <stdint.h>
     3
     4  int main()
     5  {
     6    uint32_t tmp32=0xffffffff ;
     7    uint64_t tmp64=0xa0000000ffffffff ;
     8    printf("left32:%08x\n",tmp32<<32) ;
     9    printf("left64:%016llx\n",tmp64<<64) ;
    10    printf("right32:%08x\n",tmp32>>32) ;
    11    printf("right64:%016llx\n",tmp64>>64) ;
    12    return 0 ;
    13  }

$ /usr/local/arm_linux_gnueabi/bin/arm-linux-gnueabi-gcc -v
Using built-in specs.
COLLECT_GCC=/usr/local/arm_linux_gnueabi/bin/arm-linux-gnueabi-gcc
COLLECT_LTO_WRAPPER=/usr/local/arm_linux_gnueabi/libexec/gcc/arm-linux-gnueabi/8.2.0/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../gcc-8.2.0/configure --with-pkgversion='gcc-8 b201abfd00' --enable-languages=c --prefix=/usr/local/arm_linux_gnueabi --target=arm-linux-gnueabi --with-arch=armv6 --disable-libsanitizer --disable-nls --disable-bootstrap --disable-multilib
Thread model: posix
gcc version 8.2.0 (gcc-8 b201abfd00)

$ /usr/local/arm_linux_gnueabi/bin/arm-linux-gnueabi-gcc -O0 shift_test.c
shift_test.c: In function 'main':
shift_test.c:8:31: warning: left shift count >= width of type [-Wshift-count-overflow]
   printf("left32:%08x\n",tmp32<<32) ;
                               ^~
shift_test.c:9:34: warning: left shift count >= width of type [-Wshift-count-overflow]
   printf("left64:%016llx\n",tmp64<<64) ;
                                  ^~
shift_test.c:10:32: warning: right shift count >= width of type [-Wshift-count-overflow]
   printf("right32:%08x\n",tmp32>>32) ;
                                ^~
shift_test.c:11:35: warning: right shift count >= width of type [-Wshift-count-overflow]
   printf("right64:%016llx\n",tmp64>>64) ;
                                   ^~

$ ./a.out
left32:00000000
left64:0000000000000000
right32:00000000
right64:0000000000000000

$ /usr/local/arm_linux_gnueabi/bin/arm-linux-gnueabi-gcc -O2 shift_test.c
shift_test.c: In function 'main':
shift_test.c:8:31: warning: left shift count >= width of type [-Wshift-count-overflow]
   printf("left32:%08x\n",tmp32<<32) ;
                               ^~
shift_test.c:9:34: warning: left shift count >= width of type [-Wshift-count-overflow]
   printf("left64:%016llx\n",tmp64<<64) ;
                                  ^~
shift_test.c:10:32: warning: right shift count >= width of type [-Wshift-count-overflow]
   printf("right32:%08x\n",tmp32>>32) ;
                                ^~
shift_test.c:11:35: warning: right shift count >= width of type [-Wshift-count-overflow]
   printf("right64:%016llx\n",tmp64>>64) ;
                                   ^~

$ ./a.out
left32:00000000
left64:0000000000000000
right32:00000000
right64:0000000000000000

どうやらコンパイルで生成される命令列による所があるみたい。 x86で-O0による左シフトのコンパイルでは shl命令が使用されるようですが、 この命令はシフト量を示す値が5ビットにマスクされる為、強制的に0~31の シフト量になるようです。この為、例えば 33bit左シフトさせると、 1bit左シフトしたのと同じ結果になるようです。 -O2を指定した場合はコンパイル時に値が定数0になるようです。 つまり、0になるのが意図した結果で、シフト量が mod 32 になる方が想定外という感じなのかも?
armでは左シフトのコンパイルでは lsl命令が使用されるようですが、 シフト量の指定にレジスタが使用される場合は最下位バイト(8bit)が使用 される為か32bitシフトを行えるようです。しかし、シフト量に定数(即値)も 指定できるようで、この場合は0~31の範囲しか指定できないようです。 最適化オプションによらず シフト量指定にレジスタを使用する命令列が生成 されるようなので、結果値が一定という事になってるみたい。
x86は注意が必要という感じなのかも? ただ、シフト量がコンパイル時には 決定できず実行時に判る場合、-O2でもシフトされない場合があるんじゃ なかろうか?とは思ったりも。

2019/06/12

遅めに帰着。

ちょろっとGTS。

調べ事。

2019/06/11

遅めに帰着。

あまりの眠さに急速停止。

2019/06/10

遅めに帰着。

あまりの眠さに急速停止。

2019/06/09

AM中に起床。

掃除したり洗濯したり。

perlでちょっこり雑用スクリプト。 ちょっとしたものでも構造体的なデータ構造で処理したくなる事がありますが、 個人的にperlでは連想配列を構造体風に使う事がよくあります。 ただ、毎回参照方法を忘れてしまうのでメモ。 以下のようなD言語風の構造体とその配列の場合、

struct Element
{
  int    no ;
  string name ;
  int    age ;
} ;

Element[] db ;

他にもやり方はあるかと思いますが、次のような感じで値を読み込みます。

my @db ;
$db[0]->{no}=1; $db[0]->{name}="bbb"; $db[0]->{age}=30;
$db[1]->{no}=2; $db[1]->{name}="aaa"; $db[1]->{age}=20;
$db[2]->{no}=3; $db[2]->{name}="ccc"; $db[2]->{age}=10;

取り出し方としては以下のような感じ。

print "--- original db ---\n" ;
foreach my $elm ( @db ){
    printf(" %d: name=%s , age=%d\n", $elm->{no}, $elm->{name}, $elm->{age}) ;
}

実行結果
--- original db ---
 1: name=bbb , age=30
 2: name=aaa , age=20
 3: name=ccc , age=10

この例では $db[x] は名無しの連想配列への参照という事になります。 また、「$elm->{no}」は「${$elm}{no}」と同じ意味なのですが、 伝統的な連想配列宣言した変数「%foo」を「$foo{key}」でアクセス するイメージとの関係がなんだか判りにくいです。 なので、参照方法が判らなくなって毎回調べている訳ですが(^^;;

$db[x] は名無しの連想配列への「参照」なので、例えば以下のように 「コピーしたものを少し弄るつもり」のようなコードを書くと、 元のデータを弄っている事になります。

$db[3]=$db[1] ;
$db[3]->{no}  =4 ;
$db[3]->{age}+=1 ;

実行結果

--- original db ---
 1: name=bbb , age=30
 4: name=aaa , age=21     # $db[1]に対応するデータも変わる
 3: name=ccc , age=10
 4: name=aaa , age=21     #コピーして弄ったつもりのデータ

値をコピーする場合は以下のように一時的な変数に連想配列のインスタンス をコピーして、そのインスタンスへ参照するようにしてから弄るという感じに する必要があります。

my %cpy=%{$db[1]} ;   #要素のコピーを行う
$db[3]=\%cpy ;        #$db[3]はコピーへの参照を行う
$db[3]->{no}  =4 ;
$db[3]->{age}+=1 ;

実行結果

--- original db ---
 1: name=bbb , age=30
 2: name=aaa , age=20   #コピー元のデータはそのまま
 3: name=ccc , age=10
 4: name=aaa , age=21   #名前以外は書き換わっている

「一時変数に置かなくても「$db[3]=\%{$db[1]};」で同じじゃね?」 と思ったりするのですが、これは参照のままと解釈されるので 「$db[3]=$db[1]」と同じです。あと、前述の例で 変数 %cpy を使い回すと、 これも一つのインスタンスの内容を書き換えるだけなので、思ったような コピーになりません。以下のように my で新たなインスタンスを割り当てる イメージのループに入れてコピーする必要があるようです。

for( my $i=0 ; $i<2 ; $i++ ){
    my %cpy=%{$db[1]} ;  #ループ毎に新しいインスタンスを割り当ててコピーするイメージ
    $db[3+$i]=\%cpy ;
    $db[3+$i]->{no}  =4+$i ;
    $db[3+$i]->{age}+=$i+1 ;
}

実行結果

--- original db ---
 1: name=bbb , age=30
 2: name=aaa , age=20
 3: name=ccc , age=10
 4: name=aaa , age=21
 5: name=aaa , age=22

とは言え、perl自体は変数の型の無い言語なので、構造体メンバー変数に相当する ハッシュキーをtypoすると、文法エラーにはならず(typo通りの動きではありますが) 思ったのと違う動きをして、あれぇ?となる感じかと思います。 コードも扱うデータも小さい場合はデバッグprintを入れながら確認できるとは思いますが、 巨大なリストの処理でバグってると大分面倒臭い感じになるようには思います。

Windows10の1903を入れてみたり。なんだかんだと2時間 くらいかかったような。壁紙が明るくなったのですが、個人的には 前のが良かったです。慣れの問題かも知れませんが。前の壁紙は選べない のだろうか?

2019/06/08

AM中に起床。

具合が悪くて死亡。

調べ事。

2019/06/07

遅めに帰着。

GTSボチボチ。

ちょろり調べ事。

2019/06/06

遅めに帰着。

そういやここ数日、高齢者運転による事故が何件も報道されていますが、 こんだけ報道されてるにも関わらず、何故 つぎつぎ新たに事故るんだ? とは思ったりも。

GTS。総額50億CR獲得と50億CR分車両購入のアチーブメント取得。

2019/06/05

遅めに帰着。

ちょろりGTS。

2019/06/04

遅めに帰着。

ちょろり調べ事。

2019/06/03

遅めに帰着。

ちょろりGTS。プロリーグまでの追加イベントはなんとか消化。

2019/06/02

AM中に起床。

NCURSESライブラリをD言語から使えるかと調べてみた所、マクロ関数で 少し困った実装になってたり。C言語のマクロ関数では、以下のように 書くと 引数に値渡しした変数に値が返る関数の様に書く事ができます。

#define getXY(handle, x, y)   {x=handle->x; y=handle->y;}

int func()
{
  HANDLE* handle;  //何かしら構造体で構成されるハンドラ
  int x,y;
  handle=create_handle() ;
  getXY(handle,x,y) ;
  printf("x,y=%d,%d\n",x,y) ;
    :
}

ただこれ、C言語以外の言語にバインドしようと思うと、マクロ関数と 同等の事が書けないと面倒臭い事になります。 全てハンドラと関数を介して値を受け渡せるのであれば、ハンドラが どのような物(単純なint型かも知れないし、構造体かも知れない)でも バインドする側は一切気にしなくて良いのですが、例えばハンドラが 構造体で構成されていて、メンバー変数を参照しなくてはならない 作りになっていると、バインドする側でも構造体の構成を知らなくては 値が取り出せなくなってしまいます。
他の言語にバインドするか否かは置いといたとしても、 C言語を覚え始めたばかりの人は 値渡しとポンタ渡しの違いを知る 過程の中で混乱するかも知れません。

夕方頃に散髪に。

GTS。追加されたイベントをいくつか消化。

2019/06/01

起きたら午後もいい時間。寝すぎ。

掃除したり。

プライベートでも本物お仕事でも、ちょろっとした文字列置換などに sedコマンドを使う事があります。「そんな事もできるの?」と 思うものもsedでできたりする事があるのですが、コマンド体系を イマイチ理解していないのと、perlとかスクリプトがちょっと書けたり すると、あまり調べる事無く そちらに流れてしまう感じです。 そんな訳で、今更ですがsedのコマンド体系を少し理解してみようと思ったり。

個人的によく使うのは、

  $ cat foo.txt | sed 's/foo/bar/g' > bar.txt

のような文字列置換。でも、これって色々省略されてる為、sedのコマンド体系の 全容が判りにくい例かも知れません。sedコマンド自体は

sed <開始行>,<終了行><コマンド>

の様に指定できて、開始行や終了行(==適用範囲)を省略すると全て の行に続くコマンドが適用されるという体系になっています。 先に挙げた「sed 's/foo/bar/g'」は適用範囲が省略されている (即ち全ての行に適用)という訳です。

コマンドは d(削除),s(パターン文字列を置換),p(表示;これ、ちょっとややこしい。 でもsedの内部処理を理解するのに重要)といったものがあります。

# 3~7行目を削除
$ cat foo.bin | hexdump -C -v | head -8 | cat -n |  sed '3,7d'
     1  00000000  ff d8 ff db 00 43 00 03  02 02 03 02 02 03 03 03  |.....C..........|
     2  00000010  03 04 03 03 04 05 08 05  05 04 04 05 0a 07 07 06  |................|
     8  00000070  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|

#2~+4(2+4==6)行目を削除
$ cat foo.bin | hexdump -C -v | head -8 | cat -n |  sed '2,+4d'
     1  00000000  ff d8 ff db 00 43 00 03  02 02 03 02 02 03 03 03  |.....C..........|
     7  00000060  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|
     8  00000070  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|

#パターン'00000010'を含む行から'04 05 09 05'を含む行の範囲を削除
$ cat foo.bin | hexdump -C -v | head -8 | cat -n |  sed '/00000010/,/04 05 09 05/d'
     1  00000000  ff d8 ff db 00 43 00 03  02 02 03 02 02 03 03 03  |.....C..........|
     7  00000060  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|
     8  00000070  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|

#'00000010'を含む行から+4行の範囲内の文字パターン ' 14' を ' __'に置換
$ cat foo.bin | hexdump -C -v | head -8 | cat -n |  sed '/00000010/,+4s/ 14/ __/g'
     1  00000000  ff d8 ff db 00 43 00 03  02 02 03 02 02 03 03 03  |.....C..........|
     2  00000010  03 04 03 03 04 05 08 05  05 04 04 05 0a 07 07 06  |................|
     3  00000020  08 0c 0a 0c 0c 0b 0a 0b  0b 0d 0e 12 10 0d 0e 11  |................|
     4  00000030  0e 0b 0b 10 16 10 11 13  __ 15 15 15 0c 0f 17 18  |................|
     5  00000040  16 __ 18 12 __ 15 __ ff  db 00 43 01 03 04 04 05  |..........C.....|
     6  00000050  04 05 09 05 05 09 __ 0d  0b 0d __ __ __ __ __ __  |................|
     7  00000060  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|
     8  00000070  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|

削除や置換の例は分かりやすいと思います。
少しややこしいのが コマンドp。例えば、以下のようにすればegrep風になるのかと 思ったらそうはなりません。

#パターン'000000[1-3]0'を含む行だけを表示??
$ cat foo.bin | hexdump -C -v | head -8 | cat -n |  sed '/000000[1-3]0/p'
     1  00000000  ff d8 ff db 00 43 00 03  02 02 03 02 02 03 03 03  |.....C..........|
     2  00000010  03 04 03 03 04 05 08 05  05 04 04 05 0a 07 07 06  |................|
     2  00000010  03 04 03 03 04 05 08 05  05 04 04 05 0a 07 07 06  |................|
     3  00000020  08 0c 0a 0c 0c 0b 0a 0b  0b 0d 0e 12 10 0d 0e 11  |................|
     3  00000020  08 0c 0a 0c 0c 0b 0a 0b  0b 0d 0e 12 10 0d 0e 11  |................|
     4  00000030  0e 0b 0b 10 16 10 11 13  14 15 15 15 0c 0f 17 18  |................|
     4  00000030  0e 0b 0b 10 16 10 11 13  14 15 15 15 0c 0f 17 18  |................|
     5  00000040  16 14 18 12 14 15 14 ff  db 00 43 01 03 04 04 05  |..........C.....|
     6  00000050  04 05 09 05 05 09 14 0d  0b 0d 14 14 14 14 14 14  |................|
     7  00000060  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|
     8  00000070  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|

なにやらパターンにマッチした行が2行出力されます。 この場合は以下のようにすると所望の結果が得られます。
#パターン'000000[1-3]0'を含む行だけを表示。egrep '000000[1-3]0' と同じ感じの結果が得られる。
$ cat foo.bin | hexdump -C -v | head -8 | cat -n |  sed '/000000[1-3]0/p;d'
     2  00000010  03 04 03 03 04 05 08 05  05 04 04 05 0a 07 07 06  |................|
     3  00000020  08 0c 0a 0c 0c 0b 0a 0b  0b 0d 0e 12 10 0d 0e 11  |................|
     4  00000030  0e 0b 0b 10 16 10 11 13  14 15 15 15 0c 0f 17 18  |................|

sedのWikipedia の説明によると、読み込まれた行は一旦「パターンスペース」と呼ばれる場所に 格納され、パターンスペースのデータに全ての処理が施されたらパターンスペースに 残ったデータを出力するという仕組みなのだそうです。これを踏まえて前述egrep風のsedコマンドを 解釈すると以下のようになります。


pコマンドだけでは所望の動作にならない理由が判ると思います。 dコマンドに相当する事、すなわち全ての行処理において最後にパターンスペースの内容を 出力したくない場合は、-nオプションを付加する事で dコマンドが不要になります。

#パターン'000000[1-3]0'を含む行だけを表示。
$  cat foo.bin | hexdump -C -v | head -8 | cat -n |  sed -n '/000000[1-3]0/p'
     2  00000010  03 04 03 03 04 05 08 05  05 04 04 05 0a 07 07 06  |................|
     3  00000020  08 0c 0a 0c 0c 0b 0a 0b  0b 0d 0e 12 10 0d 0e 11  |................|
     4  00000030  0e 0b 0b 10 16 10 11 13  14 15 15 15 0c 0f 17 18  |................|

ただこれ、man sed を読んでみると

       -n, --quiet, --silent

              suppress automatic printing of pattern space

と説明されてて、パターンスペースの概念が理解できていないと何の事だか判らない ように思います。

あと、今回の日記を書いててハマりそうに思った例。

#'00000010'を含む行から+4行の範囲内の文字パターン ' 14 ' を ' __ 'に置換???
$ cat foo.bin | hexdump -C -v | head -8 | cat -n |  sed '/00000010/,+4s/ 14 / __ /g'
     1  00000000  ff d8 ff db 00 43 00 03  02 02 03 02 02 03 03 03  |.....C..........|
     2  00000010  03 04 03 03 04 05 08 05  05 04 04 05 0a 07 07 06  |................|
     3  00000020  08 0c 0a 0c 0c 0b 0a 0b  0b 0d 0e 12 10 0d 0e 11  |................|
     4  00000030  0e 0b 0b 10 16 10 11 13  __ 15 15 15 0c 0f 17 18  |................|
     5  00000040  16 __ 18 12 __ 15 __ ff  db 00 43 01 03 04 04 05  |..........C.....|
     6  00000050  04 05 09 05 05 09 __ 0d  0b 0d __ 14 __ 14 __ 14  |................|
     7  00000060  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|
     8  00000070  14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14  |................|

6行目で置換されずに' 14 'のままになる場合がありました。 どうやら以下のように解釈されてるようです。

カラム番号   1234567
対象文字列  ' 14 14 '
↓↓↓↓↓↓↓↓↓↓↓↓ 最初の' 14 'の置換
カラム番号   1234567
対象文字列  ' __ 14 '
↓↓↓↓↓↓↓↓↓↓↓↓ 1~4カラム目を対象としたので、次は5カラム目からを対象とする
カラム番号   1234567
対象文字列  ' __ 14 '   結果、4~7カラム目の' 14 'は置換対象とならない

他で出現可能性があるのを防ぐために、「空白で囲まれた'14'という文字列」 として対象を絞るつもりだったのですが、前述のような副作用がある点には注意が 必要かも知れません。

コマンド体系を理解してみると、info sed の中で示されている例も 理解できる感じです。指示の内容は明確なのに指示の方法が呪文なものですから、 パっと見で何をしろって言ってるのかが良く分からないという感じかも知れません。 「sed '/apple/s/hello/world/'」とかは、「sed 's/foo/bar/'」くらいしか 使っていないと何のこっちゃ?という感じかも知れません。

Emacsでは「C-u M-|」(shell-command-on-region)でリージョンに保存された文字列を パイプで外部コマンドに渡して、その結果を元のリージョンと置き換える事ができます。 ちょっとややこし目の置換や整形はキーボードマクロでも時間がかかったりする 場合がありますので、餅は餅屋で外部コマンドに任せるのはアリかも知れません。


TOP PREV