¿Cuál es el peso de los literales binarios en C++14?


He intentado buscar pero no he sido capaz de encontrar mucho acerca de binario literales y peso. ¿Son los literales binarios little-endian, big-endian o algo más (como hacer coincidir la plataforma de destino)?

Como ejemplo, ¿cuál es el valor decimal de 0b0111? Es 7? ¿Plataforma específica? Algo más? Edit: Elegí un valor malo de 7 ya que está representado dentro de un byte. La pregunta ha sido suficientemente respondida a pesar de este hecho.

Algunos antecedentes: Básicamente estoy tratando de averiguar cuál es el valor de los bits menos significativos son, y enmascararlo con literales binarios parecía una buena manera de ir... pero sólo si hay algún tipo de garantía sobre peso.

Author: Levi Morrison, 2014-12-18

8 answers

Respuesta corta: no hay uno.

Respuesta Larga: La endianidad nunca se expone directamente en el código a menos que realmente intente sacarla (como usar trucos de puntero). 0b0111 es 7, son las mismas reglas que hex, escribiendo

int i = 0xAA77;

No significa 0x77AA en algunas plataformas, porque eso sería absurdo. ¿Dónde irían los 0 extra que faltan de todos modos con ints de 32 bits? ¿Se rellenarían en la parte delantera, luego todo se voltearía a 0x77AA0000, o se pondrían agrega después? No tengo idea de lo que alguien esperaría si ese fuera el caso.

El punto es que C++ no hace ninguna suposición sobre la endiandad de la máquina, si escribe código usando primitivas y los literales que proporciona, el comportamiento será el mismo de máquina a máquina (a menos que comience a eludir el sistema de tipos, lo que puede que tenga que hacer)

Para abordar su actualización: el número será la forma en que lo escriba. Los bits no se reordenarán o cualquier cosa, el bit más significativo está a la izquierda y el bit menos significativo está a la derecha.


Parece haber un malentendido aquí acerca de lo que es la endiandad. La endianidad se refiere a cómo los bytes se ordenan en la memoria y cómo deben ser interpretados. Si te di el número "4172 "y dije" si esto es cuatro mil ciento setenta y dos, ¿cuál es la endiandad? " realmente no puedes dar una respuesta porque la pregunta no tiene sentido. (algunos argumentan que el dígito más grande de la izquierda significa big endian, pero sin direcciones de memoria la cuestión de la endianidad no es respondible o relevante). Esto es solo un número, no hay bytes para interpretar, no hay direcciones de memoria. Suponiendo una representación entera de 4 bytes, los bytes que le corresponden son:

        low address ----> high address
Big endian:    00 00 10 4c
Little endian: 4c 10 00 00

Así que, dado cualquiera de esos y dicho "esta es la representación interna de la computadora de 4172", podría determinar si su pequeño o grande endian.

Así que ahora considere su literal binario 0b0111 estos 4 bits representan un nybble, y se pueden almacenar como

              low ---> high
Big endian:    00 00 00 07
Little endian: 07 00 00 00

Pero no tiene que preocuparse porque esto también es manejado por el hardware, el lenguaje dicta que el compilador lee de izquierda a derecha, de bit más significativo a bit menos significativo

La endianidad no se trata de bits individuales . Dado que un byte es de 8 bits, si te entrego 0b00000111 y digo " ¿es este pequeño o gran endiano?"otra vez tú no puedo decirlo porque solo tienes un byte. Endianness no reordena bits en un byte, se refiere al reordenamiento de bytes completos (a menos que, por supuesto, tenga bytes de un bit).

Usted no tiene que preocuparse acerca de lo que su equipo está utilizando internamente. {[5] } solo te ahorra el tiempo de tener que escribir cosas como

unsigned int mask = 7 // only keep the lowest 3 bits

Por escrito

unsigned int mask = 0b0111;

Sin necesidad de comentar explicando el significado del número.

 70
Author: Ryan Haining,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-27 21:19:38

Todos los literales enteros, incluidos los binarios, se interpretan de la misma manera que normalmente leemos los números (el dígito izquierdo es el más significativo).

El estándar C++ garantiza la misma interpretación de literales sin tener que preocuparse por el entorno específico en el que se encuentre. Por lo tanto, no tienes que preocuparte por la endianidad en este contexto.

De 0b0111 es siempre igual a siete.

El estándar C++ no usar los términos de peso en cuanto a número de literales. Más bien, simplemente describe que los literales tienen una interpretación consistente, y que la interpretación es la que usted esperaría.

C++ Standard - Literales enteros - 2.14.2-párrafo 1

Un literal entero es una secuencia de dígitos que no tiene punto o parte exponente, con comillas simples de separación opcionales que se ignoran al determinar su valor. Un literal entero puede tener un prefijo que especifica su base y un sufijo que especifica su tipo. El léxico el primer dígito de la secuencia de dígitos es el más significativo. Un entero binario literal (base dos) comienza con 0b o 0B y consiste en una secuencia de dígitos binarios. Un literal entero octal (base ocho) comienza con el dígito 0 y consiste en una secuencia de dígitos octales. Un entero decimal literal (base diez) comienza con un dígito distinto de 0 y consiste en una secuencia de decimales dígitos. Un entero hexadecimal literal (base dieciséis) comienza con 0x o 0X y consiste en una secuencia de dígitos hexadecimales, que incluyen los dígitos decimales y letras de a a f y de A a F con valores decimales de diez a quince. [Ejemplo: El número doce se puede escribir 12, 014, 0XC, o 0b1100. Los literales 1048576, 1'048'576, 0X100000, 0x10'0000,, y 0 ' 004 ' 000 ' 000 todos tienen el mismo valor. - ejemplo final]

Wikipedia describe lo que endianness es, y usa nuestro sistema numérico como ejemplo para entender big-endian .

Los términos endian y "endian" se refieren a la convención utilizada para interpretar los bytes que componen una palabra de datos cuando se almacenan esos bytes en la memoria del ordenador.

Los sistemas Big-endian almacenan el byte más significativo de una palabra en el dirección más pequeña y el byte menos significativo se almacena en el la dirección más grande (véase también el bit más significativo). Little-endian los sistemas, por el contrario, almacenan el byte menos significativo en el más pequeño dirección.

Un ejemplo en el endianness es pensar en cómo un número decimal es escrito y leído en notación de valor de lugar. Asumiendo un sistema de escritura donde los números se escriben de izquierda a derecha, la posición más a la izquierda es análoga a la dirección más pequeña de memoria utilizada, y más a la derecha la posición más grande. Por ejemplo, el número ciento veintitrés está escrito 1 2 3, con los cientos de lugar a la izquierda-más. Cualquiera que lea este número también sabe que el dígito más a la izquierda tiene el lugar más grande valor. Este es un ejemplo de una convención big-endian seguido en diario vida.

En este contexto, estamos considerando que un dígito de un literal entero es un "byte de una palabra", y que la palabra es el literal en sí. Además, el carácter más a la izquierda en un literal se considera que tiene la dirección más pequeña.

Con el literal 1234, los dígitos uno, dos, tres y cuatro son los "bytes de una palabra", y 1234 es la "palabra". Con el literal binario 0b0111, los dígitos cero, uno, uno y uno son los "bytes de una palabra", y la palabra es 0111.

Esta consideración nos permite entender la endianidad en el contexto del lenguaje C++, y muestra que los literales enteros son similares a "big-endian".

 39
Author: Michael Gazonda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-19 03:33:00

Que se está perdiendo la distinción entre "endian" como está escrito en el código fuente y el endianness como se representa en el código objeto. La respuesta para cada uno no es sorprendente: los literales de código fuente son bigendianos porque así es como los humanos los leen, en el código objeto se escriben sin importar cómo los lea el objetivo.

Dado que un byte es, por definición, la unidad más pequeña de acceso a la memoria, no creo que sea posible incluso atribuir una endianidad a cualquier representación interna de bits en un byte the la única manera de descubrir la endianidad para números más grandes (ya sea intencionalmente o por sorpresa) es accediendo a ellos desde el almacenamiento por partes, y el byte es, por definición, la unidad de almacenamiento accesible más pequeña.

 10
Author: jthill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-18 18:06:21

A los lenguajes C/C++ no les importa la endianidad de los enteros multibyte. Los compiladores de C/C++ lo hacen. Los compiladores analizan su código fuente y generan código máquina para la plataforma de destino específica. El compilador, en general, almacena literales enteros de la misma manera que almacena un entero; de modo que las instrucciones de la CPU de destino soportarán directamente la lectura y escritura en memoria.

El compilador se encarga de las diferencias entre las plataformas de destino para que usted no tenga que hacerlo.

El único el tiempo que necesita preocuparse por la endianidad es cuando está compartiendo valores binarios con otros sistemas que tienen diferentes órdenes de bytes.Luego leería los datos binarios, byte por byte, y organizaría los bytes en la memoria en el orden correcto para el sistema en el que se ejecuta su código.

 7
Author: Theron W Genaux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-18 17:22:22

Una imagen es a veces más que mil palabras.

fuente vs memoria endianness

 3
Author: Zoltan Tirinda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-16 13:26:43

Peso es de aplicación definido. El estándar garantiza que cada objeto tiene una representación de objeto como una matriz de char y unsigned char, con la que puede trabajar llamando a memcpy() o memcmp(). En C++17, es legal reinterpret_cast un puntero o referencia a cualquier tipo de objeto (no un puntero a void, puntero a una función, o nullptr) a un puntero a char, unsigned char, o std::byte, que son alias válidos para cualquier tipo de objeto.

Lo que la gente quiere decir cuando se habla de "peso" es el orden de bytes en esa representación de objetos. Por ejemplo, si declaras unsigned char int_bytes[sizeof(int)] = {1}; y int i; entonces memcpy( &i, int_bytes, sizeof(i)); ¿obtienes 0x01, 0x01000000, 0x0100, 0x010000000000000, o algo más? La respuesta es: sí. Hay implementaciones del mundo real que producen cada uno de estos resultados, y todos se ajustan al estándar. La razón de esto es para que el compilador pueda usar el formato nativo de la CPU.

Esto aparece más a menudo cuando un programa necesita enviar o recibir datos a través de Internet, donde todos los los estándares definen que los datos deben transmitirse en orden big-endian, en una CPU little-endian como el x86. Por lo tanto, algunas bibliotecas de red especifican si los argumentos y campos particulares de las estructuras deben almacenarse en orden de bytes de host o de red.

El lenguaje le permite dispararse en el pie girando los bits de una representación de objeto arbitrariamente, pero podría obtener una representación trap, que podría causar un comportamiento indefinido si intenta usarlo más tarde. (Esto podría significar, por ejemplo, reescribir una tabla de funciones virtuales para inyectar código arbitrario.) El encabezado <type_traits> tiene varias plantillas para probar si es seguro hacer cosas con una representación de objetos. Puede copiar un objeto sobre otro del mismo tipo con memcpy( &dest, &src, sizeof(dest) ) si ese tipo is_trivially_copyable. Puede hacer una copia a la memoria no inicializada correctamente alineada si is_trivially_move_constructible. Puede probar si dos objetos del mismo tipo son idénticos con memcmp( &a, &b, sizeof(a) ) y correctamente hash un objeto aplicando un hash función a los bytes en su representación de objeto si el tipo has_unique_object_representations. Un tipo integral no tiene representaciones trampa, y así sucesivamente. Sin embargo, en su mayor parte, si está realizando operaciones en representaciones de objetos donde la endianidad importa, le está diciendo al compilador que asuma que sabe lo que está haciendo y que su código no será portable.

Como otros han mencionado, los literales binarios se escriben con el dígito más significativo primero, como los literales decimales, octales o hexidecimales. Esto es diferente de endianness y no afectará si necesita llamar a ntohs() en el número de puerto desde un encabezado TCP leído desde Internet.

 0
Author: Davislor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-27 22:50:35

Además diré que incluso el compilador no tiene cuidado, por ejemplo en la plataforma LLVM solo el backend (técnicamente no un compilador) se encargará de endianess.

 -1
Author: ingconti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-21 08:45:53

Es posible que desee pensar en C o C++ o cualquier otro lenguaje como intrínsecamente poco endiano (piense en cómo funcionan los operadores bitwise). Si el HW subyacente es big endian, el compilador se asegura de que los datos se almacenen en big endian (ídem para otras endianidades), sin embargo, sus operaciones de bits funcionan como si los datos fueran little endian. Lo que hay que recordar es que en lo que respecta al lenguaje, los datos están en little endian. Endianness relacionados con los problemas surgen cuando lanzas los datos de de un tipo al otro. Mientras no hagas eso, eres bueno.

Me preguntaron sobre la afirmación "El lenguaje C/C++ es intrínsecamente poco endiano", como tal estoy proporcionando un ejemplo que muchos saben cómo funciona, pero bien aquí voy.

typedef union
{
    struct {
        int a:1;
        int reserved:31;
    } bits;

    unsigned int value;
} u;

u test;
test.bits.a = 1;
test.bits.reserved = 0;

printf("After bits assignment, test.value = 0x%08X\n", test.value);

test.value = 0x00000001;

printf("After value assignment, test.value = 0x%08X\n", test.value);

Salida en un pequeño sistema endian:

After bits assignment, test.value = 0x00000001
After value assignment, test.value = 0x00000001

Salida en un sistema big endian:

After bits assignment, test.value = 0x80000000
After value assignment, test.value = 0x00000001

Entonces, si no conoces la endiandad del procesador, ¿de dónde sale todo bien? en el pequeño endian el sistema! Por lo tanto, yo digo que el lenguaje C/C++ es intrínsecamente "little endian".

 -6
Author: RcnRcf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-18 22:11:16