2

次のシグネチャを持つ関数が与えられたとします。

void SendBytesAsync(unsigned char* data, T length)

type で指定できる最大長のバイト配列を保持するのに十分な大きさのバッファーが必要Tです。そのバッファを宣言するにはどうすればよいですか? sizeof型に含めることができる最大値ではなく、型 T のサイズ (バイト単位) を返すため、単に使用することはできません。基になる型が変更され、バッファーが小さすぎる可能性があるため、limits.h を使用したくありません。定数式が必要なため、math.h の pow を使用できません。では、C でコンパイル時に型の最大サイズの定数式を取得するにはどうすればよいでしょうか?

編集

タイプは unsigned になります。静的に割り当てられたバッファーがコンパイル時に決定されるという考えに誰もが愕然としているように見えるので、少し背景を説明します。これは、信頼性と速度が優先される組み込みアプリケーション (マイクロコントローラー上) 向けです。そのため、実行時の整合性 (malloc問題なし) とパフォーマンス (バッファーが必要になるたびにメモリ割り当てのオーバーヘッドがない) のために、静的に割り当てられたメモリを浪費してもまったく問題ありません。の最大サイズTが大きすぎると、リンカーがそれほど大きなバッファーを割り当てることができないというリスクを理解していますが、それは、実行時のエラーではなく、コンパイル時のエラーであり、対応できます。容認することはできません。たとえば、私が使用する場合size_tペイロードのサイズを調べてメモリを動的に割り当てると、システムで使用可能なメモリがそれほど多くない可能性が非常に高くなります。これは、パケットの損失やデータの破損などを引き起こす実行時よりも、コンパイル時に知りたいと思います。私が提供した関数シグネチャを見ると、動的な割り当てられたバッファーであり、呼び出し元が型の最大値を使用する可能性を期待しないでください。したがって、そのメモリを一度割り当てることについて、なぜそれほど多くの驚きがあるように見えるのか、私にはわかりません。これは、複数のプロセスが同じメモリ リソースをめぐって争っている Windows の世界では大きな問題であることがわかりますが、組み込みの世界では、実行するタスクは 1 つだけであり、それを効果的に実行できない場合は、それを実行できません。

4

5 に答える 5

4

使用_Generic:

#define MAX_SIZE(X) _Generic((X),
                             long: LONG_MAX,
                             unsigned long: ULONG_MAX,
                             /* ... */)

C11 より前では、タイプ T のオブジェクトの正確な最大値を見つけるための移植可能な方法はありません (CHAR_BITたとえば、 を使用したすべての計算では、パディング ビットのために過大​​評価が生じる可能性があります)。

編集:特定の条件下(実際の状況のセグメント化されたメモリを考えてください)では、特定のタイプ T の最大値に等しい十分な大きさのバッファを割り当てることができない場合があることに注意してください。

于 2012-08-20T21:10:17.400 に答える
2

T が符号なしの場合、((T) -1) は機能しますか?

(これはおそらく本当に悪いことです。もしそうなら、理由を教えてください:-))

于 2012-08-20T21:03:19.570 に答える
1

少しシフトを使ってみては?

どれどれ:

unsigned long max_size = (1 << (8 * sizeof(T))) - 1

sizeof(T) は、T がメモリ内で占有するバイト数を示します。(技術的には真実ではありません。通常、コンパイラは構造をメモリに合わせます...したがって、Tが1バイトの場合、実際には4または何かを割り当てます。)

それを分解する:

8 * sizeof(T)サイズが表すビット数を示します

1 << xと言っているのと同じ2 to the x powerです。左にシフトするたびに、2 倍になるからです。基数 10 で左にシフトするたびに、10 を掛けているのと同じように。

- 18 ビットの数値は 256 個の値を保持できます。0..255。

于 2012-08-20T21:07:06.730 に答える
0

興味深い質問です。数値型 T の最大値の「制限」ヘッダーを調べることから始めます。試したことはありませんが、T::max を使用する何かを行います。

于 2012-08-20T21:07:03.623 に答える