切腹のイラスト

Cで文字列のコピー

{
  date: "",
}

Cを勉強していた頃のはなし。

char str_cpy_from[]="abcdef";
char str_cpy_to[100];
char* pos_cpy_from=str_cpy_from;
char* pos_cpy_to=str_cpy_to;

while (*pos_cpy_to++ = *pos_cpy_from++);

printf("\"%s\" -> \"%s\"\n", str_cpy_from, str_cpy_to);

昔は,実際に他の(for文を回したりする)実装のコードと比べて,コンパイラが吐くバイナリが短くて速かったらしい。

コードの意味するところ

大前提,Cでの文字列はcharが並んで最後にNULL文字があり(例えば"abc"{'a','b','c',0}みたいな感じ),printfとかは文字列の終端をこのNULL文字によって判断している(ゆえに適当なchar配列の途中に0の要素を挟んでやるとそこで出力が止まってしまう)。

インクリメント演算子は結合の優先度が高いようで,while文の条件式のところの代入文の右辺*pos_cpy_from++*(pos_cpy_from++)ということになり,ループごとにpos_cpy_fromポインタ(とpos_cpy_toポインタ)がインクリメントされることになる。

また,代入文は値として評価できるっぽいので,ポインタの実体が偽(=0)になるまでpos_cpy_fromの指すchar型の値は*pos_cpy_toに代入され続ける。

これを関数として定義するならvoid f(char*, char*)といったところか。

実は

この書き方は”プログラミング言語C”という超有名な本で紹介されているらしい。

ただ最近はコンパイラも優秀になっていて,普通のプログラミングにおいて,わざわざ人力でわかりづらい最適化を行うことに対する見返りは少ない。

あとlibc(string.h)にstrcpyという関数があるので普段はそっちを使う。 つまり,自分でこんな機能の関数を実装する機会はない。