Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

390
Views
C vs C ++ colocando estructuras en un búfer de caracteres sin firmar

¿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).

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

¿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.

over 4 years ago · Santiago Trujillo Report

0

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:

  • simplemente emita el puntero y acceda a él y compile con -fno-strict-aliasing , o use volatile
  • o mueva el acceso al búfer a otro archivo que se compila sin LTO para que el compilador simplemente no pueda optimizarlo.

 // 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; }
over 4 years ago · Santiago Trujillo Report

0

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". ".

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!