我目前的(简化版)缓冲区API如下:
typedef struct {
size_t offset;
size_t size;
uint8_t *data;
} my_buffer;
// Writes an unsigned int 8 to the buffer
bool my_buffer_write_u8(my_buffer *buffer, uint8_t value) {
if (buffer->offset >= buffer->size) return false;
buffer->data[buffer->offset] = value;
++buffer->offset;
return true;
}
然而,在我重新了解C语言中的严格别名规则后,我对这种用法并不确定:
char string[32];
my_buffer buffer;
buffer.size = sizeof(string);
buffer.data = string; // <-- I think this violates the strict aliasing rule
buffer.offset = 0;
// the function calls access buffer.data which is defined to be `uint8_t *` and not `char *`
// in other words, I'm manipulating a `char *` through a `uint8_t *`:
// even though uint8_t is almost always unsigned char, it is nevertheless not the same as unsigned char
my_buffer_write_u8(&buffer, 'h');
my_buffer_write_u8(&buffer, 'e');
my_buffer_write_u8(&buffer, 'l');
my_buffer_write_u8(&buffer, 'l');
my_buffer_write_u8(&buffer, 'o');
my_buffer_write_u8(&buffer, '\0');
我认为在缓冲区结构体中应该使用 void *
,然后使用 (char *)
类型转换来访问底层数据:
typedef struct {
size_t offset;
size_t size;
void *data;
} my_buffer;
// Writes an unsigned int 8 to the buffer
bool my_buffer_write_u8(my_buffer *buffer, uint8_t value) {
if (buffer->offset >= buffer->size) return false;
unsigned char *data = (unsigned char *)buffer->data;
data[buffer->offset] = value;
++buffer->offset;
return true;
}
char *
、unsigned char *
以及signed char *
总是被假定为与其他数据类型别名相同。
但是对于uint8_t *
来说,情况不尽相同(按照标准来说)。
如果CHAR_BIT
等于8
,那么带有(void *)
的这个调整后的代码应该与uint8_t
版本完全相同。
现在问题来了:我是否正确地应用了严格别名规则?
char *
,但如果重构麻烦,您可以添加断言,即uint8_t
和unsigned char
是相同的。 - tstanisl