17歳からのプログラミング入門。

情報系の門の先で起きたことをたまにメモ。

プログラマの端は書き捨て。

kosen13s' Advent Calendar 2016 (http://www.adventar.org/calendars/1855) の 3 日目の記事です。

これは供養です!

先日、半年ほど使っていた Xubuntu 15.10 の仮想マシンに別れを告げ Xubuntu 16.10 に乗り換えたのですが、 前のディスクの tmp ディレクトリに大量のプログラムが書き捨てられていました。

f:id:Iruyan_Zak:20161203234928p:plain

人からの相談や、耳にした tips などを tmp に投げ入れているため、 もう用のないコードではありますが、もしかしたら誰かの知見になりうるかと思うので、公開します。

ただし、本当に意味のわからないコードもあるので、紹介するのは一部だけです。

/0523

C++ の deprecated を用いたコンパイル時型表示のプログラムです。

#include<bits/stdc++.h>
class H{};

template <class T>
[[deprecated]] void chk_type(T t){}

int main(){
    auto cache = new std::unordered_map<int, std::weak_ptr<const H>>;
    chk_type(cache);
}

これをコンパイルすると

a.cpp: In function ‘int main()’:
a.cpp:10:19: warning: ‘void chk_type(T) [with T = std::unordered_map<int, std::weak_ptr<const H> >*]’ is deprecated [-Wdeprecated-declarations]
     chk_type(cache);
                   ^
a.cpp:6:21: note: declared here
 [[deprecated]] void chk_type(T t){}
                     ^

このような警告が出て、 cache の型の推論結果が表示されます。 一節には、そこらの IDE では推論できない推論結果まで教えてくれるらしいです。

/0830

https://speakerdeck.com/greymd/mei-ri-kou-keru-sieruyun-wojue-eyou?slide=31 これで遊んでた時の残骸だと思う。シェル芸いいよ。 xaa ってこれわけわからずに split 打った出力だよなあ。

% ls 0830
fuga  hoge  holidays  xaa

あと、同時期に "man コマンドクイズ" ってのにもはまってました。

man vim を実行すると vim - Vi IMproved, プログラマのテキストエディタ と表示され、 vim はエディタであるとわかるのですが、 man emacs を実行すると emacs - GNU project Emacs と表示され、「EmacsEmacsだ」という強い意志を感じることができます。

/0904

C++ラムダ式は関数ポインタに突っ込めるんだなあ・・・。 これで最適化を封じて時間計測する、みたいな技があると聞いた気がする。

#include<iostream>
using namespace std;

int main(void){
    int (*hoge)(int) = [](int n){ return n*n; };
    cout << hoge(10) << endl;
}

/0921

mkfifo ってコマンドを使うと名前付きパイプっていう面白いファイルを作ることができます。 もしかしたら環境によってコマンド名は違うかも。

% ls 0921
echo hello  fifo|  hello@  p|  preprocess.c

何ができるかは説明すると長くなるんだけど、2つのプロセスからこのファイルへの書き出しと読み出しが両方行われた時に初めて、2つのプロセスに書き出しと読み出しを行わせる(それまではブロックする)っていう挙動をします。

何に使えるかわからん。

/1024

やさしい C のポインタのお話。 言いたいことはすべてコメントになってる。

#include<stdio.h>

int main(){
    char h[4];
    h[0] = 1;
    h[1] = 2;
    h[2] = 3;
    h[3] = 4;

    // ポインタなんて所詮整数だからビット演算にかけられたりするよ
    printf("%p, %zu\n", h, (size_t)h);
    printf("%d\n", *(char*)((size_t)(h+3) & (-4)));

    putchar('\n');

    // ポインタなんて所詮その変数が格納されている"先頭の"アドレスでしかないから、サイズの違う型のポインタにキャストしてやればもともとの変数の境界なんてうやむやにできるよ
    *((short*)h+1) = *(short*)h;
    for(int i=0; i<4; i++) printf("%d\n", h[i]);

    putchar('\n');

    // short はここでは 2 バイト整数型として、それらを 1 バイトずつ表示。リトルエンディアン方式により下位のバイトが先行するのが見える
    short a = 258;
    printf("%d, %d", *(char*)&a, *((char*)&a+1));
}

この話を後輩に面白く話せるようになれたらいいなあ。 このコードが欲しければ好きに持って行ってください。

/1119

split コマンドの挙動を調べたくなったので、 sudo apt-get source coreutils してソースを拾ってきました。

いろんなコマンドの実装が読めて楽しいです。

% ls 1119
coreutils-8.23/                  coreutils_8.23-4ubuntu2.dsc  hgoe   xaa  xac
coreutils_8.23-4ubuntu2.diff.gz  coreutils_8.23.orig.tar.gz   pipe/  xab  xad

あとがき

思ったより何書いてるかわからないものが多くて抜粋に苦労しました。 広く浅く、いろんな言語、いろんな分野をやっているので、 面白い tips をご存じの方はぜひ教えて下さい!