トリッキーコードネット トップへ戻る   C/C++, Java, Perl, PHP, JavaScript, アルゴリズム, ショートコーディング, IOCCCコードの解説, 等々

サイト情報

トリッキーなコード

7行プログラミング

物凄いコード集

アルゴリズム

データ構造

C/C++な話題

コードサンプル

ツール/環境構築

開発ノウハウ 等

ネタ/ジョーク集

おススメ書籍/サイト

サイトTOP >> トリッキーなコード >> Duff's device(ダフのデバイス)について (C言語)

Duff's device(ダフのデバイス)について (C言語)

Duffという人が考えた Duff's deviceという、有名なC言語のトリッキーコードがあります^^;)

それがこちらのコード↓↓

/* countは 「 必ずcount > 0 である」という前提 */
switch (count % 8)
 {
   case 0:  do {  *to = *from++;
   case 7:        *to = *from++;
   case 6:        *to = *from++;
   case 5:        *to = *from++;
   case 4:        *to = *from++;
   case 3:        *to = *from++;
   case 2:        *to = *from++;
   case 1:        *to = *from++;
            } while ((count -= 8) > 0);
 }
do {} whileの中にcase文が入っていて、見るからに怪しさ満点のコードなのですが、 なんとビックリ、このコードはC言語の正当なコーディング手法なんだそうです! ( ゚Д゚)・・・ポカーン ※補足しておくと、case文とはただのラベルに過ぎず、ブロック中にあっても有効 (これをcaseラベルのfall-through特性というらしい)との事。 そして、上記コードは、以下のコードを最適化したものです。
do {
   *to = *from++;
 } while (--count > 0);
連続コピーを行うコードなのですが、メモリマップされたデバイスの出力レジスタへのコピーの為、 *toにインクリメントがつきません。 ループ展開することによって、処理を高速化しています。 ・・・ということで、早速テスト開始~♪
#include <stdio.h>
#include <string.h>
#include <malloc.h>

int main(void)
{
    char * psz1 = calloc(100, sizeof(char));
    char * psz2 = "abcdefghijklmnopqrstuvwxyz";
    char * to   = psz1;
    char * from = psz2;

    int  count  = (int)strlen(from);

    do {
        *to++ = *from++;
    } while (--count > 0);

    // *to = NULL;

    puts(psz1);
    puts(psz2);
}
文字列をコピーするテストコードです^^;) PCでテストする際は、*toにインクリメントをつけます。 また、callocではなくmallocでメモリ領域を割当てた場合は、最後に *to = NULLをするのを忘れないようにします。 実行結果は以下の通り Duff's deviceの実験結果1 そして、Duff's device風にコードを書き換えて実行してみます。
#include <stdio.h>
#include <string.h>
#include <malloc.h>

int main(void)
{
    char * psz1 = calloc(100, sizeof(char));
    char * psz2 = "abcdefghijklmnopqrstuvwxyz";
    char * to   = psz1;
    char * from = psz2;

    int  count  = (int)strlen(from);

    switch (count % 8) {
       case 0:  do {  *to++ = *from++;
       case 7:        *to++ = *from++;
       case 6:        *to++ = *from++;
       case 5:        *to++ = *from++;
       case 4:        *to++ = *from++;
       case 3:        *to++ = *from++;
       case 2:        *to++ = *from++;
       case 1:        *to++ = *from++;
                } while ((count -= 8) > 0);
     }

    puts(psz1);
    puts(psz2);
}
実行結果は以下の通り Duff's deviceの実験結果2 最適化前のコードと同じ動作をしていることが、無事に確認できました~^^;) ちなみに、最適化前コードの以下の部分は、
int  count  = (int)strlen(from);

do {
    *to++ = *from++;
} while (--count > 0);
以下の様に書き直すことができます。
while (*to++ = *from++);
K&Rで推奨されている、strcpyのやり方です。
ひょっとしたら参考になるかもしれないページ : switchステートメント
         このエントリーをはてなブックマークに追加   


作業効率化・ライフハックのオススメ記事




コンピュータ・テクノロジーのオススメ記事





恋愛・人間関係のオススメ記事




※ 当サイトは、トップページからリンクで辿る事の出来るページに限り、リンクフリーです。
※ 当サイトの閲覧/利用によって生じた如何なる損害も、当サイト管理人は責任を負いません。
※ 当サイトの内容を転載される場合は、当サイトへのリンクをお願い致します。