だから私は64回目のバッファリングライブラリを書き込もうとしていて、かなり高度なものに取り掛かっています。私はこれについていくつかの専門家の意見を求めたいと思いました。
私の最初のヘッダーファイルにはこれがあります:
typedef struct StdBuffer { void* address; } StdBuffer;
extern void StdBufferClear(StdBuffer);
私がこれを持っている最初のヘッダーファイルである別のヘッダーファイルで#includes
:
typedef struct CharBuffer { char* address; } CharBuffer;
void (*CharBufferClear)(CharBuffer) = (void*) StdBufferClear;
この関数ポインタをvoidと宣言すると、呼び出しが妨げられますか?それらには、値の署名による一致があります。私はこれまでvoidと宣言された関数ポインタを見たことがありませんが、それをきれいにコンパイルする唯一の方法です。
スタック的には、アセンブラーコーディングで学んだこととまったく違いはありません。
無関係なOMG!StackOverflowでStackwiseと言いました!
うーん..ここで想定しすぎたようです。よろしければ、はっきりさせておきます。アドレスに保存されているデータの「タイプ」は関係ありません。私が懸念しているのは、「ユニット」のサイズとアドレスにあるユニットの数だけです。次の場合は、APIのインターフェース契約を確認してください。
typedef struct StdBuffer {
size_t width; ///< The number of bytes that complete a data unit.
size_t limit; ///< The maximum number of data units that can be allocated for this buffer.
void * address; ///< The memory address for this buffer.
size_t index; ///< The current unit position indicator.
size_t allocated; ///< The current number of allocated addressable units.
StdBufferFlags flags;///< The API contract for this buffer.
} StdBuffer;
ほら、memcpy、memmoveなどは、アドレスの内容を気にしないでください。必要なのは、ここで明確に追跡している詳細だけです。
この契約に従う最初のプロトタイプを今すぐ見てください:
typedef struct CharBuffer {
size_t width; ///< The number of bytes that complete a data unit.
size_t limit; ///< The maximum number of data units that can be allocated for this buffer.
char * address; ///< The memory address for this buffer.
size_t index; ///< The current unit position indicator.
size_t allocated; ///< The current number of allocated addressable units.
CharBufferFlags flags;///< The API contract for this buffer.
} CharBuffer;
はっきりとわかるように、このコンテキストではデータ型は無関係です。Cは場合によって処理が異なると言えますが、結局のところ、同じマシンでメモリを処理している限り、anaddress
はaddress
、a、byte
is byte
、along
はaです。long
このシステムをまとめた目的は、このタイプベースのジャグリングCをすべて削除することです。これは、私がやりたいことには無意味です。これは、任意のアドレスにある任意の標準サイズのデータ(1、2、4、8、sizeof(RandomStruct))のプロトタイプを順守するコントラクトを作成することです。
コードを使用して独自のキャストを実行し、特定の長さのメモリユニットを使用して特定の長さのメモリブロックを操作するAPI関数を使用してそのデータを操作する機能を備えています。ただし、プロトタイプには公式のデータポインター型が含まれている必要があります。これは、エンドユーザーがそのアドレスポインターで何かを実行するたびにデータを再キャストする必要があることは意味がないためです。ポインタがvoidの場合、これをCharBufferと呼ぶのは意味がありません。
これStdBuffer
は、API自体の内部を除いて、すべてのコントラクトに準拠したデータ型を管理するために使用されることのないジェネリック型です。
このシステムに組み込まれるAPIは、私の最新版のバッファリングからのものです。これは、@ Google Codeで非常に明確に文書化されています。これをすべてまとめるには、いくつかの変更が必要になることを認識しています。つまり、適切な調査と意見の収集がなければ、API内からデータを安全に直接操作することはできません。
これは、StdBufferFlagsメンバーにSigned/Unsignedビットフラグも必要であることに気づきました。
おそらく、このパズルの最後のピースは、あなたが熟読するためのものでもあります。
/** \def BIT(I)
\brief A macro for setting a single constant bit.
*
* This macro sets the bit indicated by I to enabled.
* \param I the (1-based) index of the desired bit to set.
*/
#define BIT(I) (1UL << (I - 1))
/** \enum StdBufferFlags
\brief Flags that may be applied to all StdBuffer structures.
* These flags determine the contract of operations between the caller
* and the StdBuffer API for working with data. Bits 1-4 are for the
* API control functions. All other bits are undefined/don't care bits.
*
* If your application would like to use the don't care bits, it would
* be smart not to use bits 5-8, as these may become used by the API
* in future revisions of the software.
*/
typedef enum StdBufferFlags {
BUFFER_MALLOCD = BIT(1), ///< The memory address specified by this buffer was allocated by an API
BUFFER_WRITEABLE = BIT(2), ///< Permission to modify buffer contents using the API
BUFFER_READABLE = BIT(3), ///< Permission to retrieve buffer contents using the API
BUFFER_MOVABLE = BIT(4) ///< Permission to resize or otherwise relocate buffer contents using the API
}StdBufferFlags;