3

根底にあるタイプを捨てずに、ボラティリティだけを捨てる方法を探しています。私はC++で知ってconst_castいますが、これを単純な古いCで行う同等の方法があるかどうか疑問に思っています。

問題は、揮発性ポインタを介してアクセスされる共有メモリデータベースと、不揮発性ポインタで動作するBツリーライブラリがあることです。(ツリーは検索中にロックされるため、コンパイラーはBツリーライブラリ内の揮発性について心配する必要はありません)。

また、2つをリンクし、ポインターから揮発性物質をキャストする自動生成コードが大量にあります。残念ながら、今日、誰かがデータベース内の間違った構造を使用してツリーノードを定義し、その自動生成されたキャストがコンパイラから問題を完全に隠していました。

4

2 に答える 2

2

少し注意が必要ですが、ポインタ型からポインタ型に変換するだけの場合は、ここでプリプロセッサを利用できます。

#define cv_cast(TYPE,expr) (*((TYPE)(expr)) = *(expr),(TYPE)(expr))

使用法:

typedef struct {
  float f;
} Foo;

typedef struct {
  char b;
} Bar;

void somefunction(void) {
  Foo f; Bar b;
  Foo volatile* foov = &f;
  Foo* foo = 0;
  Bar* bar = &b;
  foo = cv_cast(Foo*,foov); // legal (no error, no warning)
  foov = cv_cast(Foo*,foo); // legal (no error, no warning)
  foo = cv_cast(Foo*,bar); // illegal (an error)
}

ここでの基本的なトリックは、fromからBartoへの割り当てを強制することです。これは、の後の部分で行われます。互換性のないポインタ型をキャストしている場合にのみ、エラーがトリガーされます。Foocv_castBar*Foo*,

ただし、cv_cast無効な場所(たとえばNULL)を指すポインタを使用すると、segfaultが発生することに注意してください。


注:(コメント内の)参照用に、この投稿nullfnでは以前は不要なヘルパー関数を使用していました。興味があれば、履歴で調べることができます。

于 2012-04-12T15:20:07.803 に答える
1

Cは型の安全性に関してあまり多くを持っていません、コンパイル時にそのようなバグを見つけるのを助ける標準には何もありません。明示的な型キャストを使用すると、型が完全に失われ、未定義の動作が残る可能性があります。

そのようなタイプキャストが表示されるのではないかと心配している場合は、いつでも何らかのマクロを作成して、そのようなエラーを書きにくくすることができると思います。

#define PTR_CONST_CAST(type, ptr) ((type*)ptr)

volatile int* const ptr_original;
int* ptr_new;

ptr_new = PTR_CONST_CAST(int, ptr_original); 
/* Note: here I am casting away volatile and const because... */

このマクロは、型の安全性をまったく追加しません。しかし、少なくともそれはプログラマーに恐らく危険な型キャストを認識させ、うまくいけばバグを書く前に彼らに二度考えさせます。特定の場合にそうすることが安全である理由を表すコメントも良い習慣です。

しかし、すべての誤ったキャストを取り除くための唯一の真剣な方法は、最初にコンパイラの警告を最大に調整することです。複数のコンパイラでコンパイルします。また、コンパイラが自由に無視できるものを見つけるための専用の静的分析ツールを使用してコードを実行します。

于 2012-04-12T15:19:26.423 に答える