¿Existe una definición de macro de una línea para determinar el endianness de la máquina? Estoy usando el siguiente código, pero convertirlo a macro sería demasiado largo.
unsigned char test_endian( void )
{
int test_var = 1;
unsigned char *test_endian = (unsigned char*)&test_var;
return (test_endian[0] == 0);
}
c
architecture
macros
endianness
manav mn
fuente
fuente
0
lugar deNULL
en su prueba final, y cambiar uno de lostest_endian
objetos a otra cosa :-).#if
directiva.Respuestas:
Código que admite órdenes de bytes arbitrarias, listo para colocarse en un archivo llamado
order32.h
:Verificaría sistemas little endian a través de
fuente
char
? Mejor usouint8_t
y falla si este tipo no está disponible (que puede ser verificado por#if UINT8_MAX
). Tenga en cuenta queCHAR_BIT
es independiente deuint8_t
.O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 */
Si tiene un compilador que admita literales compuestos C99:
o:
Sin embargo, en general, debe intentar escribir código que no dependa del endianness de la plataforma host.
Ejemplo de implementación de host-endianness-independiente de
ntohl()
:fuente
ntohl
de una manera que no dependa del endianness de la plataforma de host.No existe un estándar, pero en muchos sistemas, incluso
<endian.h>
le dará algunas definiciones para buscar.fuente
#if __BYTE_ORDER == __LITTLE_ENDIAN
y#elif __BYTE_ORDER == __BIG_ENDIAN
. Y generar un#error
elsewise.<endian.h>
no está disponible en Windowsendian.h
menos que se defina__APPLE__
o_WIN32
.#if BYTE_ORDER == LITTLE_ENDIAN
(oBIG_ENDIAN
) sin guiones bajos antes de los nombres._BYTE_ORDER
es solo para encabezados del sistema.__BYTE_ORDER
no existe.Para detectar endianness en tiempo de ejecución, debe poder hacer referencia a la memoria. Si se apega al estándar C, declarar una variable en la memoria requiere una declaración, pero devolver un valor requiere una expresión. No sé cómo hacer esto en una sola macro; es por eso que gcc tiene extensiones :-)
Si está dispuesto a tener un archivo .h, puede definir
y luego puedes usar la
ENDIANNESS
macro como quieras.fuente
Si solo desea confiar en el preprocesador, debe averiguar la lista de símbolos predefinidos. La aritmética del preprocesador no tiene el concepto de direccionamiento.
GCC en Mac define
__LITTLE_ENDIAN__
o__BIG_ENDIAN__
Luego, puede agregar más directivas condicionales de preprocesador basadas en la detección de plataforma, como
#ifdef _WIN32
etc.fuente
#define __BIG_ENDIAN__ 1
y#define _BIG_ENDIAN 1
.#define __LITTLE_ENDIAN__ 1
. Esta macro parece ser una característica de clang, no una característica de gcc. Elgcc
comando en algunas Mac no es gcc, es clang.Creo que esto es lo que se pidió. Solo probé esto en una pequeña máquina endian bajo msvc. Alguien por favor confirme en una máquina Big Endian.
Como nota al margen (específica del compilador), con un compilador agresivo puede usar la optimización de "eliminación de código muerto" para lograr el mismo efecto que un tiempo de compilación
#if
como este:Lo anterior se basa en el hecho de que el compilador reconoce los valores constantes en el momento de la compilación, elimina por completo el código interno
if (false) { ... }
y reemplaza el código comoif (true) { foo(); }
enfoo();
el peor de los casos: el compilador no realiza la optimización, aún obtiene el código correcto pero un poco más lento.fuente
'ABCD'
?clang -Wpedantic -Werror -Wall -ansi foo.c
y se producirá un error. (Clang y esto específicamente:-Wfour-char-constants -Werror
)Si está buscando una prueba de tiempo de compilación y está usando gcc, puede hacer:
Consulte la documentación de gcc para obtener más información.
fuente
__BYTE_ORDER__
está disponible desde GCC 4.6De hecho, puede acceder a la memoria de un objeto temporal utilizando un literal compuesto (C99):
Qué GCC evaluará en el momento de la compilación.
fuente
#if __STDC_VERSION__ >= 199901L
.La 'biblioteca de red C' ofrece funciones para manejar endian'ness. Es decir, htons (), htonl (), ntohs () y ntohl () ... donde n es "red" (es decir, big-endian) y h es "host" (es decir, el endian'ness de la máquina que ejecuta el código).
Estas 'funciones' aparentes se definen (comúnmente) como macros [consulte <netinet / in.h>], por lo que no hay una sobrecarga de tiempo de ejecución para usarlas.
Las siguientes macros utilizan estas 'funciones' para evaluar la endianidad.
Adicionalmente:
La única vez que necesito saber la endianidad de un sistema es cuando escribo una variable [en un archivo / otro] que puede ser leída por otro sistema de endianidad desconocida (para compatibilidad multiplataforma ) ... En casos como estos, es posible que prefiera utilizar las funciones endian directamente:
fuente
Utilice una función en línea en lugar de una macro. Además, necesita almacenar algo en la memoria que es un efecto secundario no tan agradable de una macro.
Puede convertirlo en una macro corta usando una variable estática o global, como esta:
fuente
s_endianess
establece en 1 para empezar?Si bien no hay un #define portátil o algo en lo que confiar, las plataformas proporcionan funciones estándar para convertir hacia y desde su endian 'host'.
Por lo general, el almacenamiento (en disco o en la red) se realiza mediante 'network endian', que es BIG endian, y computación local mediante host endian (que en x86 es LITTLE endian). Usas
htons()
yntohs()
y amigos para convertir entre los dos.fuente
fuente
No olvide que el endianness no es toda la historia: el tamaño de
char
podría no ser de 8 bits (por ejemplo, DSP), la negación del complemento a dos no está garantizada (por ejemplo, Cray), es posible que se requiera una alineación estricta (por ejemplo, SPARC, también ARM se coloca en el medio -endian cuando no está alineado), etc., etc.En su lugar, podría ser una mejor idea apuntar a una arquitectura de CPU específica .
Por ejemplo:
Tenga en cuenta que, lamentablemente, esta solución tampoco es ultraportátil, ya que depende de definiciones específicas del compilador (no existe un estándar, pero aquí hay una buena compilación de tales definiciones).
fuente
Prueba esto:
fuente
Preste atención a que la mayoría de las respuestas aquí no son portátiles, ya que los compiladores de hoy evaluarán esas respuestas en tiempo de compilación (depende de la optimización) y devolverán un valor específico basado en una endianidad específica, mientras que la endianidad real de la máquina puede diferir. Los valores en los que se prueba el endianness nunca llegarán a la memoria del sistema, por lo que el código ejecutado real devolverá el mismo resultado independientemente del endianness real.
Por ejemplo , en ARM Cortex-M3 la endianidad implementada se reflejará en un bit de estado AIRCR.ENDIANNESS y el compilador no puede conocer este valor en tiempo de compilación.
Salida de compilación para algunas de las respuestas sugeridas aquí:
https://godbolt.org/z/GJGNE2 para esta respuesta,
https://godbolt.org/z/Yv-pyJ para esto respuesta, y así sucesivamente.
Para resolverlo, necesitará usar el
volatile
calificador.Yogeesh H T
's respuesta es la más cercana para el uso de la vida real de hoy, pero comoChristoph
sugiere solución más completa, una ligera corrección a su respuesta sería la respuesta completa, sólo tiene que añadirvolatile
a la declaración de la Unión:static const volatile union
.Esto aseguraría el almacenamiento y la lectura de la memoria, que es necesaria para determinar la endianidad.
fuente
Si vuelca el preprocesador #defines
Por lo general, puede encontrar cosas que lo ayudarán. Con lógica de tiempo de compilación.
Sin embargo, varios compiladores pueden tener diferentes definiciones.
fuente
Mi respuesta no es la que se le preguntó, pero ¿es realmente sencillo averiguar si su sistema es little endian o big endian?
Código:
fuente
Código C para comprobar si un sistema es little-endian o big-indian.
fuente
Macro para encontrar endiannes
o
fuente