所以我第 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 的函数指针,但它是让它干净编译的唯一方法。
Stackwise 它应该与我在汇编程序编码中学到的东西没有任何区别。
无关紧要的天哪!我刚刚在 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
就是 an address
, abyte
是byte
和 along
是 a 。long
这个系统组合在一起的目的是消除所有这种类型的杂耍 C 似乎很自豪(而且理所当然地......)它对我想做的事情毫无意义。这是为位于任何地址的任何标准大小的数据(1、2、4、8、sizeof(RandomStruct))创建一个遵守合同的原型。
能够使用代码执行我自己的转换,并使用 api 函数操作该数据,这些函数在具有特定长度内存单元的特定长度内存块上运行。但是,原型必须包含官方数据指针类型,因为最终用户每次想要使用该地址指针做某事时都必须重新转换他们的数据是没有意义的。如果指针为空,则称其为 CharBuffer 是没有意义的。
是一种通用类型,除了在 api 本身内之外,StdBuffer
永远不会使用它来管理所有遵守合同的数据类型。
该系统将包含的 api 来自我最新版本的缓冲。@Google Code这里非常清楚地记录了这一点,我知道有些事情需要改变才能将这一切整合在一起,即如果没有大量适当的研究和意见收集,我将无法直接从 api 中安全地操作数据。
这让我注意到我还需要 StdBufferFlags 成员中的有符号/无符号位标志。
也许这个谜题的最后一部分也是为了让你细读。
/** \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;