【发布时间】:2021-12-10 11:27:27
【问题描述】:
我当前的(简化的)缓冲区 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 版本完全相同。
现在问题是:我是否正确应用了严格别名规则?
【问题讨论】:
标签: c buffer strict-aliasing