39

同じ型の typedef に明示的なキャストを強制する方法はありますか? 私は utf8 に対処する必要があり、文字数とバイト数のインデックスと混同されることがあります。したがって、いくつかの typedef があると便利です。

typedef unsigned int char_idx_t;
typedef unsigned int byte_idx_t;

それらの間に明示的なキャストが必要であることに加えて:

char_idx_t a = 0;
byte_idx_t b;

b = a; // compile warning
b = (byte_idx_t) a; // ok

そのような機能がCに存在しないことは知っていますが、それを行うトリックまたはコンパイラ拡張機能(gccが望ましい)を知っているかもしれません。


編集 私はまだハンガリー語の表記法が一般的にあまり好きではありません。プロジェクトのコーディング規則のため、この問題には使用できませんでしたが、タイプも同じで意味も非常に似ている別の同様のケースで使用しました。そして、私は認めなければなりません:それは役に立ちます。「i」で始まるすべての整数を宣言するつもりはありませんが、ジョエルの重複する型の例のように、命を救うことができます。

4

9 に答える 9

22

「ハンドル」型 (不透明なポインター) の場合、Microsoft は、構造体を宣言してから、構造体へのポインターを typedef するというトリックを使用します。

#define DECLARE_HANDLE(name) struct name##__ { int unused; }; \
                             typedef struct name##__ *name

次に、代わりに

typedef void* FOOHANDLE;
typedef void* BARHANDLE;

彼らは:

DECLARE_HANDLE(FOOHANDLE);
DECLARE_HANDLE(BARHANDLE);

だから今、これは動作します:

FOOHANDLE make_foo();
BARHANDLE make_bar();
void do_bar(BARHANDLE);

FOOHANDLE foo = make_foo();  /* ok */
BARHANDLE bar = foo;         /* won't work! */
do_bar(foo);                 /* won't work! */   
于 2008-12-17T23:49:54.153 に答える
19

次のようなことができます:

typedef struct {
    unsigned int c_idx;
} char_idx;

typedef struct {
    unsigned int b_idx;
} byte_idx;

次に、それぞれをいつ使用しているかがわかります。

char_idx a;
byte_idx b;

b.b_idx = a.c_idx;  

これで、それらが異なる型であることがより明確になりましたが、それでもコンパイルされます。

于 2008-12-17T23:45:42.507 に答える
14

必要なものは「strongtypedef」または「stricttypedef」と呼ばれます。

一部のプログラミング言語[Rust、D、Haskell、Ada、...]は、言語レベルでこれをサポートしますが、C[++]はサポートしません。「opaquetypedef」という名前の言語に含めるという提案がありましたが、受け入れられませんでした。

ただし、言語サポートの欠如は実際には問題ではありません。エイリアス化するタイプを、タイプTのデータメンバーが1つだけある新しいクラスにラップするだけです。繰り返しの多くは、テンプレートとマクロによって除外できます。この単純な手法は、直接サポートされているプログラミング言語と同じくらい便利です。

于 2009-10-23T16:05:20.933 に答える
7

糸くずを使用します。Splint:Typesstrong type checkを参照してください。

厳密な型チェックにより、プログラミング エラーが明らかになることがよくあります。Splint は、一般的なコンパイラ (4.1) よりも厳密かつ柔軟にプリミティブ C 型をチェックでき、ブール型 (4.2) をサポートします。さらに、ユーザーは情報隠蔽 (0) を提供する抽象型を定義できます。

于 2008-12-17T23:51:53.463 に答える
5

C では、コンパイラによって適用されるユーザー定義型間の唯一の違いは、 structs間の違いです。個別の構造体を含むすべての typedef が機能します。あなたの主な設計上の問題は、異なる構造体型が同じメンバー名を使用する必要があるかということです。 もしそうなら、マクロやその他の壊滅的なトリックを使用して、いくつかのポリモーフィック コードをシミュレートできます。そうでない場合は、2 つの異なる表現に真剣に取り組んでいます。例:できるようになりたいですか?

#define INCREMENT(s, k) ((s).n += (k))

INCREMENTとの両方byte_idxで使用しchar_idxます。次に、フィールドに同じ名前を付けます。

于 2008-12-18T04:21:15.667 に答える
3

C++11 では、enum クラスを使用できます。

enum class char_idx_t : unsigned int {};
enum class byte_idx_t : unsigned int {};

コンパイラは、2 つの型の間で明示的なキャストを強制します。これは薄いラッパー クラスのようなものです。残念ながら、演算子のオーバーロードはありません。たとえば、2 つの char_idx_t を一緒に追加したい場合は、それらを unsigned int にキャストする必要があります。

于 2013-10-24T17:36:09.940 に答える
3

あなたは拡張機能について尋ねました。Jeff Foster のCQualは非常に優れており、必要な機能を実行できると思います。

于 2009-02-26T06:35:45.297 に答える
2

C++ を作成している場合、unsigned int のラッパーである、名前が異なる 2 つの同一に定義されたクラスを作成できます。Cであなたがやりたいことをするためのトリックを知りません。

于 2008-12-17T23:36:57.690 に答える
1

BOOST_STRONG_TYPEDEFで定義されている強力な typedef を使用する

于 2010-05-02T13:53:20.933 に答える