我當前的(簡化的)緩沖區 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版本完全相同。
現在的問題是:我是否正確應用了嚴格別名規則?
uj5u.com熱心網友回復:
如果uint8_t與unsigned char.Assuming 不同,它將是 UB,uint8_t因為它非常不可能
- CHAR_BIT 至少為 8,參見http://port70.net/~nsz/c/c11/n1570.html#5.2.4.2.1p1
- unsigned char 沒有填充位
- unsigned char 是最小的可尋址單位
但是,標準沒有明確要求uint8_t與unsigned char. 因此,它是實作定義的。
考慮應用以下執行緒中的解決方案來檢查上述型別是否相同。 c - 如何斷言兩種型別在c中相等?
最好使用char*/unsigned char*來訪問資料。但是,如果代碼的重構會很麻煩,那么只需添加檢查型別uint8_t和unsigned char是否相同,如果不同則拒絕編譯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/336496.html
