¿Cómo puedo desactivar el relleno de estructura en C sin usar pragma?Desactivar el relleno de estructura en C sin usar pragma
Respuesta
no existe una norma forma de hacer esto. La norma establece que el relleno se puede hacer a discreción de la implementación. De C99 6.7.2.1 Structure and union specifiers
, párrafo 12:
Cada miembro no campo de bits de una estructura o unión objeto está alineado de una manera definida por la implementación apropiada a su tipo.
Habiendo dicho eso, hay un par de cosas que puedes probar.
El primero que ya ha descontado, usando #pragma
para tratar de convencer al compilador que no empacar. En cualquier caso, esto no es portátil. Tampoco existen otras formas específicas de implementación, pero debe verificarlas, ya que puede ser necesario hacerlo si realmente necesita esta capacidad.
La segunda es de pedir sus campos de mayor a menor orden, como todos los tipos long long
seguidos por los long
queridos, entonces todos los int
, short
y finalmente char
tipos. Por lo general, esto funcionará, ya que con mayor frecuencia son los tipos más grandes los que tienen los requisitos de alineación más estrictos. De nuevo, no es portátil.
En tercer lugar, puede definir sus tipos como char
matrices y emitir las direcciones para asegurar que no hay relleno. Pero tenga en cuenta que algunas arquitecturas se ralentizarán si las variables no están alineadas correctamente y otras fallarán miserablemente (como por ejemplo, al generar un error de BUS y al finalizar su proceso).
Este último contiene algunas explicaciones adicionales. Digamos que tiene una estructura con los campos en el orden siguiente:
char C; // one byte
int I; // two bytes
long L; // four bytes
con relleno, que puede terminar con los siguientes bytes:
CxxxIIxxLLLL
donde x
es el relleno.
Sin embargo, si se define su estructura como:
typedef struct { char c[7]; } myType;
myType n;
que se obtiene:
CCCCCCC
A continuación, puede hacer algo como:
int *pInt = &(n.c[1]);
int *pLng = &(n.c[3]);
int myInt = *pInt;
int myLong = *pLng;
a DOY:
CIILLLL
De nuevo, desafortunadamente, no es portátil.
Todas estas "soluciones" que se basan en tener un conocimiento íntimo de su compilador y los tipos de datos subyacentes.
Nota, en algunos sistemas que acceden a direcciones desalineadas ('int * pLng = & (n.c [3]); int myLong = * pLng;' fallará en absoluto (por ejemplo, 68000 y ARM fallará). Entonces se requiere relleno allí. – Vovanium
De acuerdo, @Vovanium, de ahí mi comentario de "fracasar miserablemente". – paxdiablo
Aparte de las opciones del compilador como pragma pack, no se puede, el relleno está en el estándar C.
Siempre se puede tratar de reducir el acolchado al declarar los tipos más pequeños pasada en la estructura como en:
struct _foo {
int a; /* No padding between a & b */
short b;
} foo;
struct _bar {
short b; /* 2 bytes of padding between a & b */
int a;
} bar;
Nota para las implementaciones que tienen límites de 4 bytes
En algunas arquitecturas, la propia CPU se opondrá si se le solicita trabajar con datos mal alineados. Para evitar esto, el compilador podría generar múltiples instrucciones de lectura o escritura alineadas, desplazar y dividir o combinar los diversos bits. Es razonable esperar que sea 5 o 10 veces más lento que el manejo de datos alineado. Pero, el Estándar no requiere que los compiladores estén preparados para hacer eso ... dado el costo de rendimiento, simplemente no tiene suficiente demanda. Los compiladores que admiten control explícito sobre el relleno proporcionan sus propios pragmas precisamente porque los pragmas están reservados para la funcionalidad no estándar.
Si debe trabajar con datos no rellenos, considere escribir sus propias rutinas de acceso. Es posible que desee experimentar con tipos que requieren menos alineación (por ejemplo, use char/int8_t), pero aún es posible que, p. el tamaño de las estructuras se redondeará a múltiplos de 4, lo que frustraría las estructuras de embalaje con fuerza, en cuyo caso deberá implementar su propio acceso para toda la región de la memoria.
O bien le permite al compilador hacer el relleno, o le dice que no lo haga usando #pragma, o bien usa algunos grupos como una matriz de caracteres, y construye todos sus datos usted mismo (desplazando y agregando bytes). Esto es realmente ineficiente, pero controlarás exactamente el diseño de los bytes. Lo hice a veces preparando paquetes de red a mano, pero en la mayoría de los casos es una mala idea, incluso si es estándar.
Si realmente quiere estructuras sin relleno: defina tipos de datos de reemplazo para abreviar, int, largo, etc., utilizando estructuras o clases que están compuestas solo de bytes de 8 bits. Luego, componga sus estructuras de nivel superior utilizando los tipos de datos de reemplazo.
La sobrecarga del operador de C++ es muy conveniente, pero se podría lograr el mismo efecto en C usando estructuras en lugar de clases. Las implementaciones de reparto y asignación siguientes suponen que la CPU puede manejar enteros desalineados de 32 bits, pero otras implementaciones podrían acomodar CPU más estrictas.
Aquí es código de ejemplo:
#include <stdint.h>
#include <stdio.h>
class packable_int { public:
int8_t b[4];
operator int32_t() const { return *(int32_t*) b; }
void operator = (int32_t n) { *(int32_t*) b = n; }
};
struct SA {
int8_t c;
int32_t n;
} sa;
struct SB {
int8_t c;
packable_int n;
} sb;
int main() {
printf ("sizeof sa %d\n", sizeof sa); // sizeof sa 8
printf ("sizeof sb %d\n", sizeof sb); // sizeof sb 5
return 0;
}
Podemos desactivar el relleno estructura en el programa de c utilizando cualquiera de los métodos siguientes.
-> use __attribute__((packed))
detrás de la definición de structure. por ej.
struct node {
char x;
short y;
int z;
} __attribute__((packed));
-> use -fpack-struct
marca mientras compila el código c. por ej.
$ gcc -fpack-struct -o tmp tmp.c
Espero que esto ayude. Gracias.
- 1. desactivar el mensaje #pragma ("...") en Visual C++?
- 2. Desactivar localmente el relleno
- 3. Relleno de estructura en C++
- 4. C/C++: datos de relleno o relleno en una estructura
- 5. ¿desactivar el valor de relleno de vector en el tamaño? C++
- 6. ¿Debo usar "#pragma GCC ..." o "#pragma clang ..." en Xcode
- 7. Uso de #pragma en C
- 8. Cómo suprimir una advertencia del compilador en C# sin usar #pragma?
- 9. C++ # paquete de pragma
- 10. ¿Qué significa #pragma en C?
- 11. pasando una estructura sobre el socket TCP (SOCK_STREAM) en C
- 12. Alineación de estructura en Visual C++
- 13. El uso de Pragma-s de SQLite en C#
- 14. Cómo usar desactivar SSL
- 15. ¿Cómo puede saber el diseñador de C# la propiedad predeterminada para un relleno u otro objeto/estructura en C#
- 16. Alineación de la estructura C en la memoria FLASH interna
- 17. Usando pragma intrínseco (sqrt, pow) en C#?
- 18. ¿Es posible inicializar una estructura sin usar una función?
- 19. Cómo deshabilitar las advertencias de #pragma?
- 20. ¿Una forma de encontrar el tamaño y la ubicación del relleno en una estructura?
- 21. Deserializar cadena JSON en C# sin usar el reflejo
- 22. C estructura y C++ estructura
- 23. ¿Cómo usar enum dentro de una estructura en ANSI C?
- 24. cadenas Relleno STL en C++
- 25. Clase de amigo sin usar en C++
- 26. En PHP, ¿cómo puedo agregar a una cadena numérica sin relleno y conservar el relleno cero?
- 27. ¿Qué estructura de datos usar?
- 28. el pragma "maestro" de OpenMP no debe estar encerrado en el pragma "paralelo para"
- 29. alineación de miembro de estructura: ¿es posible suponer que no hay relleno
- 30. Desactivar el seguimiento en el modelo de estructura de entidad primero
Esto no es estándar. Si (y, si es así, cómo) esto es posible depende completamente de la implementación de C que esté utilizando. –
Creo que no hay otra manera de hacer esto. – frast
¿Por qué no puedes usar pragma? –