¿Tiene C algo similar a C++ donde uno puede colocar estructuras en un búfer de caracteres sin firmar como se hace en C++ como se muestra en la sección estándar ? 6.7.2
template<typename ...T> struct AlignedUnion { alignas(T...) unsigned char data[max(sizeof(T)...)]; }; int f() { AlignedUnion<int, char> au; int *p = new (au.data) int; // OK, au.data provides storage char *c = new (au.data) char(); // OK, ends lifetime of *p char *d = new (au.data + 1) char(); return *c + *d; // OK }En CI, ciertamente puede memcpy una estructura de cosas (o int como se muestra arriba) en un búfer de caracteres sin firmar, pero luego, al usar un puntero a esta estructura, uno se encuentra con violaciones estrictas de alias; el búfer tiene un tipo declarado diferente.
Así que supongamos que uno quisiera replicar la segunda línea en f el C++ anterior en C. Uno haría algo como esto
#include<string.h> #include<stdio.h> struct Buffer { unsigned char data[sizeof(int)]; }; int main() { struct Buffer b; int n = 5; int* p = memcpy(&b.data,&n,sizeof(int)); printf("%d",*p); // aliasing violation here as unsigned char is accessed as int return 0; } A menudo se sugieren uniones, es decir union Buffer {int i;unsigned char b[sizeof(int)]}; pero esto no es tan bueno si el objetivo del búfer es actuar como almacenamiento (es decir, colocar tipos de diferentes tamaños allí, avanzando un puntero en el búfer a la parte libre + potencialmente un poco más para una alineación adecuada).
¿Has probado a usar un union ?
#include <string.h> #include <stdio.h> union Buffer { int int_; double double_; long double long_double_; unsigned char data[1]; }; int main() { union Buffer b; int n = 5; int *p = memcpy(&b.data, &n, sizeof(int)); printf("%d", *p); // aliasing violation here as unsigned char is accessed as int return 0; } El Buffer alinea el miembro data según el tipo con el mayor requisito de alineación.
Sí, debido a la estricta regla de alias, simplemente no es posible. Como no es posible escribir un malloc() compatible con el estándar.
Su búfer no está alineado: es necesario alignas(int) de stdalign.h .
Si desea protegerse contra las optimizaciones del compilador, ya sea:
-fno-strict-aliasing , o use volatile // mybuffer.c #include <stdalign.h> alignas(int) unsigned char buffer[sizeof(int)]; void *getbuffer() { return buffer; } // main.c #include <string.h> #include <stdio.h> #include "mybuffer.h" int main() { void *data = getbuffer(); // int *p = new (au.data) int; // OK, au.data provides storage int *p = data; // char *c = new (au.data) char(); // OK, ends lifetime of *p char *c = data; *c = 0; // char *d = new (au.data + 1) char(); char *d = (char*)data + 1; *d = 0; return *c + *d; }Por la forma en que está escrita la definición de tipo efectivo en 6.5p6, no está claro qué se supone que significa en todos los casos de esquina, probablemente porque nunca hubo un consenso entre los miembros del comité sobre cómo se deben manejar todos los casos de esquina. Los informes de defectos a menudo agregan más confusión que claridad, ya que utilizan términos como "miembro activo" de un sindicato cuando ni el Estándar ni los informes de defectos especifican qué acciones lo establecerían o cambiarían.
Si uno quiere usar un objeto de duración estática o automática como si fuera un búfer sin un tipo declarado, una forma segura de hacerlo debería ser algo como lo siguiente:
void volatile *volatile dummy_vp; void test(void) { union { char dat[1000]; unsigned long force_alignment; } buffer; void *volatile launder = buffer.dat; dummy_vp = &launder; void *storage_blob = launder; ... } A menos que una implementación se desvíe de su camino para probar si la lectura de launder produjo una dirección que coincida con buffer.dat , no tendría forma de saber si el objeto en esa dirección tenía un tipo declarado. Nada en el Estándar prohibiría que una implementación se comportara sin sentido si la dirección coincidiera con la de buffer.dat , pero es probable que las situaciones en las que las mejoras de rendimiento justifiquen el costo de la verificación no sean lo suficientemente comunes como para que los compiladores intenten tal "optimización". ".