Mi API de búfer actual (simplificada) se ve así:
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; }Sin embargo, después de actualizar mi conocimiento sobre la estricta regla de alias en C, no estoy tan seguro acerca de este caso de uso:
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'); Creo que debería usar void * en la estructura del búfer y usar una (char *) para acceder a los datos subyacentes:
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; } Porque char * , char * unsigned char * signed char * siempre se asumen como alias de otros tipos de datos.
No se puede decir lo mismo de uint8_t * (según el estándar que sea)
Si CHAR_BIT es 8 , entonces este código ajustado con (void *) debería hacer exactamente lo mismo que con la versión uint8_t .
Ahora a la pregunta: ¿he aplicado correctamente la regla de aliasing estricto?
Sería UB si uint8_t fuera diferente del unsigned char . Suponiendo que exista uint8_t , es muy poco probable porque
Sin embargo, el estándar no requiere explícitamente que uint8_t sea del mismo tipo que unsigned char . Por lo tanto, es más bien una implementación definida.
Considere aplicar la solución del siguiente hilo para comprobar que los tipos mencionados son los mismos. ¿Cómo afirmar que dos tipos son iguales en c?
Es preferible utilizar char* / unsigned char* para acceder a los datos. Sin embargo, si la refactorización del código fuera engorrosa, simplemente agregue una verificación si los tipos uint8_t y unsigned char son iguales y rechace la compilación si no lo es.