12

typedef の一般的な使用法は、変数の「型」を有効にして、変数の背後にあるストレージ構造を再定義することなく、変数の目的をより適切に伝えることです。

ただし、変数のクラスのストレージ構造を一度に変更する方法として、typedef も見ています。

たとえば、私が定義した場合

typedef uint32_t my_offset_t

printf / scanf の場合を除いてmy_offset_t、コードベースを oruint32_tからcharorに切り替えるのはuint64_t、1行を変更して再コンパイルするのと同じくらい簡単です(sizeofハードコードされたサイズではなく、使用したと仮定します)。

printf/ scanf、if-elses、またはifdefsの周りのラッパー関数なしで、タイプに応じてフォーマット指定子を簡単な方法で交換する方法はありますか?

ありがとう!

興味のある人のために、私は 16 ビット オフセットを使用して 32 ビット オフセットで動作する LKM を変更していますが、必要に応じて最小限の変更で 64 ビット (または他の何か!) オフセットに移行できるようにしたいと考えています。

4

3 に答える 3

9

これはトリッキーなビジネスですが、<inttypes.h>C99 以降ではその方法が示されています。

定義されたタイプごとに、標準化された名前空間を避けるように注意しながら、適切な「PRI」および「SCN」マクロのセットを提供する必要があります。

たとえば、XYZ をプロジェクト固有のプレフィックスとして使用して、次のように生成できます。

XYZ_PRIx_my_offset_t
XYZ_PRId_my_offset_t
XYZ_PRIX_my_offset_t
XYZ_PRIu_my_offset_t
XYZ_PRIo_my_offset_t

および SCN に相当するもの。さらに、これらを基本型の同等のマクロに関して定義すると、次のようになります。

#define XYZ_PRIx_my_offset_t PRIx32
#define XYZ_PRId_my_offset_t PRId32
#define XYZ_PRIX_my_offset_t PRIX32
#define XYZ_PRIu_my_offset_t PRIu32
#define XYZ_PRIo_my_offset_t PRIo32

コードでは、XYZ_PRIx_my_offset_tマクロを使用してフォーマット文字列を作成します。

printf("Offset: 0x%.8" XYZ_PRIX_my_offset_t "\n", my_offset_value);

その後、すべてを 64 ビットに変更する必要がある場合は、typedef とマクロ定義を適切に編集します。残りのコードは「変更されない」ままです。本当に気をつけていれば、完全に変わらない状態にかなり近づけることができます。

多くの警告が設定された状態で、32 ビットと 64 ビットの両方のシステムでコンパイルするようにしてください。GCC は、現在のプラットフォームでは問題がないことを警告しませんが、別のプラットフォームでは表示される場合があります。(64 ビットではクリーンであるが 32 ビットではクリーンではないコードをいくつか修正しました。XYZ_PRId_int4代わりにマクロ like を使用し、%d両方でクリーンにコンパイルするようになりました。)

于 2012-05-09T00:49:32.993 に答える
7

inttypes.h に関する以前の質問を見ると、システム定義の書式指定子を ( 経由で) typedef と組み合わせて使用​​し#defineて、カスタム型のカスタム印刷指定子を作成する方法がわかります。

于 2012-05-09T00:13:47.620 に答える
0

もう 1 つの解決策は、符号付きの型intmax_tuintmax_t符号なしの型を相互に変換することです。例えば:

printf("%ju\n", (uintmax_t)n);

nが符号なしタイプの場合、正しく機能します。

関数の場合*scanf()、一時オブジェクトを読み取ってから割り当てる必要があります。

(これは、ランタイム ライブラリがこれらの機能をサポートしていることを前提としています。)

于 2012-05-09T02:26:33.850 に答える