1時間ごとに更新!Amazon.co.jpで今売れている本トップ100   掲示板ランキング


掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板1

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.5550

フラグ変数のフラグを論理型へ変換
投稿者---chu-(2006/03/07 03:21:20)


テスト環境:LSIC

フラグ変数のフラグを論理型へ変換する場合、いろいろな記述が考えられます。
ifの条件としてならばAがシンプルで使いやすいのですが、論理型への変換としては使えません。
かといってBは気持ち悪いですし、Cはちょっと冗長な気がしています。
Dあたりが複数のフラグの組合せにも使える汎用性があって良いのかなぁなどと考えています。
どれでも良いと言えば良いのですが、一般的なスタイルが気になったのでご意見お聞かせください。

#include <stdio.h>

typedef signed char bool;
enum { FALSE, TRUE };
typedef unsigned short ushort;

int main(void)
{
    const ushort flag = 0x8000;
    ushort flags = 0xF0F0;
    bool on;

/*  on = flags & flag;                        /* A *//* ダメ */
/*  on = !!(flags & flag);                    /* B */
/*  on = (flags & flag) ? TRUE : FALSE;       /* C */
    on = (flags & flag) == flag;              /* D */
    if ( on ) {
        printf("ON\n");
    }
    else {
        printf("OFF\n");
    }

    return 0;
}



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:フラグ変数のフラグを論理型へ変換 5553 nop 2006/03/07 09:05:57
<子記事> Re:フラグ変数のフラグを論理型へ変換 5554 くまさん 2006/03/07 10:58:55
<子記事> Re:フラグ変数のフラグを論理型へ変換 5555 円零 2006/03/07 11:30:33
<子記事> Re:フラグ変数のフラグを論理型へ変換 5556 たかぎ 2006/03/07 13:32:46
<子記事> Re:フラグ変数のフラグを論理型へ変換 5558 chu- 2006/03/08 23:35:15


No.5553

Re:フラグ変数のフラグを論理型へ変換
投稿者---nop(2006/03/07 09:05:57)


そもそも、「Cで論理型を作ろう」と言うのが間違いでは?
Cの規格で論理値と言えば、0か!0のどちらかですから。


この投稿にコメントする

削除パスワード

No.5554

Re:フラグ変数のフラグを論理型へ変換
投稿者---くまさん(2006/03/07 10:58:55)


そもそも、
>typedef signed char bool;
というのが、一般的ではないかも。

どうしてもsigned charにしたいのなら、
#define bool_cast(x) ( (x) != 0 )

on = bool_cast(flags & flag);

てな感じにするのがいいかと思います。


この投稿にコメントする

削除パスワード

No.5555

Re:フラグ変数のフラグを論理型へ変換
投稿者---円零(2006/03/07 11:30:33)


WindowsXP / VC++6.0の環境ですが、
ためしにアセンブリコード出してみました。
コンパイラオプションは /O2 /FAcs

; 14   :     on = !!(flags & flag);                    /* B */

  00028 8b 55 f8            mov     edx, DWORD PTR _flags$[ebp]
  0002b 81 e2 ff ff 00 00   and     edx, 65535      ; 0000ffffH
  00031 8b 45 f4            mov     eax, DWORD PTR _flag$[ebp]
  00034 25 ff ff 00 00      and     eax, 65535      ; 0000ffffH
  00039 23 d0               and     edx, eax
  0003b f7 da               neg     edx
  0003d 1b d2               sbb     edx, edx
  0003f f7 da               neg     edx
  00041 88 55 fc            mov     BYTE PTR _on$[ebp], dl

; 15   :     on = (flags & flag) ? TRUE : FALSE;       /* C */

  00044 8b 4d f8            mov     ecx, DWORD PTR _flags$[ebp]
  00047 81 e1 ff ff 00 00   and     ecx, 65535      ; 0000ffffH
  0004d 8b 55 f4            mov     edx, DWORD PTR _flag$[ebp]
  00050 81 e2 ff ff 00 00   and     edx, 65535      ; 0000ffffH
  00056 23 ca               and     ecx, edx
  00058 f7 d9               neg     ecx
  0005a 1b c9               sbb     ecx, ecx
  0005c f7 d9               neg     ecx
  0005e 88 4d fc            mov     BYTE PTR _on$[ebp], cl

; 16   :     on = (flags & flag) == flag;              /* D */

  00061 8b 45 f8            mov     eax, DWORD PTR _flags$[ebp]
  00064 25 ff ff 00 00      and     eax, 65535      ; 0000ffffH
  00069 8b 4d f4            mov     ecx, DWORD PTR _flag$[ebp]
  0006c 81 e1 ff ff 00 00   and     ecx, 65535      ; 0000ffffH
  00072 23 c1               and     eax, ecx
  00074 8b 55 f4            mov     edx, DWORD PTR _flag$[ebp]
  00077 81 e2 ff ff 00 00   and     edx, 65535      ; 0000ffffH
  0007d 33 c9               xor     ecx, ecx
  0007f 3b c2               cmp     eax, edx
  00081 0f 94 c1            sete    cl
  00084 88 4d fc            mov     BYTE PTR _on$[ebp], cl
Dはちょっとだけ遅いかも。


この投稿にコメントする

削除パスワード

No.5556

Re:フラグ変数のフラグを論理型へ変換
投稿者---たかぎ(2006/03/07 13:32:46)
http://takagi.in/


> どれでも良いと言えば良いのですが、一般的なスタイルが気になったのでご意見お聞かせください。

一般的かどうかはともかく、C99ならstdbool.hをインクルードすれば、boolやtrueやfalseが使えますし、bool型のオブジェクトに代入したり、boo型にキャストすれば、元の値が非0ならtrueに、0ならfalseにコンパイラが変換してくれます。(_Boolを使うつもりならヘッダも不要です)

LSI-Cではこういった方法は無理ですので、普通の整数型を使うことになるのでしょうが...

> on = !!(flags & flag); /* B */

私ならこの方法を使います。真理値を1か0で表す目的に使っていることが明らかだからです。

> on = (flags & flag) ? TRUE : FALSE; /* C */

この方法は一見明快ですが、TRUEの値が本当に1なのかどうかは見た瞬間にはわかりません。真理値を非0と0で区別するのであれば、Aの方法でもよいはずですから、そういう意味ではCの書き方では思考が一瞬遅れます。

> on = (flags & flag) == flag; /* D */

この書き方は目的が違うと思います。例えば、flagに複数のビットが立っているような場合に使う方法で、単純に真理値に変換するだけの目的なら、読み手を混乱させます。



この投稿にコメントする

削除パスワード

No.5557

Re:フラグ変数のフラグを論理型へ変換
投稿者---RAPT(2006/03/08 01:21:39)


windowsなんかだと、

typedef int BOOL;
#define TRUE 1
#define FALSE 0

とかなってたり、Cで僕が個人的に良くやるのが、
typedef enum BOOL{
  FALSE = 0, TRUE = 1;
} BOOL;

とかだったりします。
# 良いか悪いかは別として。

あとは既出のものと大差ありませんが、下記のようなマクロでラップするとか。
#define check_flag(flags, flag) ((flags) & (flag) != 0)



この投稿にコメントする

削除パスワード

No.5558

Re:フラグ変数のフラグを論理型へ変換
投稿者---chu-(2006/03/08 23:35:15)


さまざまなご意見ありがとうございました。
どれも非常に参考になりました。

> on = bool_cast(flags & flag);

なるほど、確かにこの問題は[論理型への変換]というよりは[論理型へのキャスト]です。
C99やC++では暗黙の型変換が行われるようですし、標準に論理型の無いC89では、
記述方法を工夫するよりもマクロを定義してしまうのが一番スマートだと感じました。

キャストを目立たせる、_castで検索できる等、他にもメリットがありそうですし、
他の標準型用(long_cast等)とともにヘッダでの定義を検討してみます。
他のキャストもマクロで統一すればbool_castだけ浮くことも無くなりますね。

typedef     signed char     bool;
typedef     signed char     schar;
typedef     unsigned char   uchar;
typedef     unsigned short  ushort;
typedef     unsigned int    uint;
typedef     unsigned long   ulong;

#define     bool_cast(x)        ((x) != 0)
#define     char_cast(x)        ((char)(x))
#define     schar_cast(x)       ((schar)(x))
#define     uchar_cast(x)       ((uchar)(x))
#define     short_cast(x)       ((short)(x))
#define     ushort_cast(x)      ((ushort)(x))
#define     int_cast(x)         ((int)(x))
#define     uint_cast(x)        ((uint)(x))
#define     long_cast(x)        ((long)(x))
#define     ulong_cast(x)       ((ulong)(x))

#define     bool_ptr_cast(x)    ((bool *)(x))
#define     char_ptr_cast(x)    ((char *)(x))
#define     schar_ptr_cast(x)   ((schar *)(x))
#define     uchar_ptr_cast(x)   ((uchar *)(x))
#define     short_ptr_cast(x)   ((short *)(x))
#define     ushort_ptr_cast(x)  ((ushort *)(x))
#define     int_ptr_cast(x)     ((int *)(x))
#define     uint_ptr_cast(x)    ((uint *)(x))
#define     long_ptr_cast(x)    ((long *)(x))
#define     ulong_ptr_cast(x)   ((ulong *)(x))



この投稿にコメントする

削除パスワード

No.5559

Re:フラグ変数のフラグを論理型へ変換
投稿者---RiSK(2006/03/08 23:55:29)


以下は主観。

>記述方法を工夫するよりもマクロを定義してしまうのが一番スマートだと感じました。

これは私もそうだと思いますが

>他の標準型用(long_cast等)とともにヘッダでの定義を検討してみます。
>他のキャストもマクロで統一すればbool_castだけ浮くことも無くなりますね。

には反対。
なぜ普通にキャストしないのか読み手は考えるのではないでしょうか?
それにポインタまで考えると,例えば int****** とか出てきたら
それもマクロにするのでしょうか? そんなメンテはしたくないです。


この投稿にコメントする

削除パスワード

No.5560

Re:フラグ変数のフラグを論理型へ変換
投稿者---RAPT(2006/03/09 01:02:26)


# 良いか悪いかは別として
chu-さんの「"_cast" でgrepしたい」と、
RiSKさんの「なぜ普通にキャストしないのか」からヒントを得て、
「CからC++に移行するための参考のため」と銘打ってみました。

#ifdef __cplusplus
  // for C++
  #define c_static_cast(TYPE, EXPR)       static_cast<TYPE>(EXPR)
  #define c_reinterpret_cast(TYPE, EXPR)  reinterpret_cast<TYPE>(EXPR)
  #define c_const_cast(TYPE, EXPR)        const_cast<TYPE>(EXPR)
#else
  // for C
  #define c_static_cast(TYPE, EXPR)       ((TYPE)(EXPR))
  #define c_reinterpret_cast(TYPE, EXPR)  ((TYPE)(EXPR))
  #define c_const_cast(TYPE, EXPR)        ((TYPE)(EXPR))
  // dynamic_castに相当するC-styleのキャストはないので省略
#endif



この投稿にコメントする

削除パスワード

No.5562

Re:フラグ変数のフラグを論理型へ変換
投稿者---chu-(2006/03/09 02:13:06)


返信ありがとうございます。

> なぜ普通にキャストしないのか読み手は考えるのではないでしょうか?

うーん、確かに。
あまり言語を改造して独り善がりに走ってはいけませんね。(楽しいんですけどね)
診断室の"Pascalが好き"、になるところでした。

通常は、on = ((flags & flag) != 0);を使用し、
あまりに頻度が多い場合だけマクロを定義することにします。
on = !!(flags & flag);はシンプルでいいのですが、!の数を間違えてハマりそうなのでやめておきます。

> あとは既出のものと大差ありませんが、下記のようなマクロでラップするとか。
> #define check_flag(flags, flag) ((flags) & (flag) != 0)

C/C++の変な演算子優先順位では下記になると思います。
#define check_flag(flags, flag) (((flags) & (flag)) != 0)

# C/C++の等価演算子や関係演算子とビット演算子の変な優先順位は誰が喜ぶんでしょうね。



この投稿にコメントする

削除パスワード

No.5563

Re:フラグ変数のフラグを論理型へ変換
投稿者---たかぎ(2006/03/09 10:35:23)
http://takagi.in/


> # C/C++の等価演算子や関係演算子とビット演算子の変な優先順位は誰が喜ぶんでしょうね。

いまさら変更すると、そんな仕様変更をした奴を呪う人の方が多いことは間違いありません。



この投稿にコメントする

削除パスワード

No.5564

Re:フラグ変数のフラグを論理型へ変換
投稿者---RAPT(2006/03/10 00:33:47)


> C/C++の変な演算子優先順位では下記になると思います。
> #define check_flag(flags, flag) (((flags) & (flag)) != 0)
あ、すみません、カッコを書き忘れていました。



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧




掲示板提供:(有)リアル・インテグリティ