Quiero guardar un 4-byte int en una matriz de char… de tal manera que los primeros 4 lugares de la matriz de char son los 4 bytes de la int.

Entonces, me quieren tirar la int de nuevo fuera de la matriz…

Asimismo, los puntos de bonificación si alguien me puede dar el código para hacer esto en un bucle… es decir a la escritura como 8 enteros en un 32 matriz de bytes.

int har = 0x01010101;
char a[4];
int har2;

//write har into char such that:
//a[0] == 0x01, a[1] == 0x01, a[2] == 0x01, a[3] == 0x01 etc.....

//then, pull the bytes out of the array such that:
//har2 == har

Gracias chicos!

EDICIÓN: Asumir int son 4 bytes…

EDIT2: por Favor, no se preocupan por el endianness… voy a preocupar «endian». Sólo quiero maneras diferentes para lograr lo anterior en C/C++. Gracias

EDIT3: Si usted no puede decir, estoy tratando de escribir una serialización de la clase en el nivel bajo… así que estoy buscando diferentes estrategias para serializar algunos tipos de datos.

  • Tal vez usted debe hacer su tarea… Y luego, si tienes alguna duda, puedes publicar tu código aquí y trataremos de ayudarte a continuación. Si usted no trate de hacerlo usted mismo, usted no va a aprender nada.
  • LOL esto no es la tarea 🙂
  • Si estuviera escribiendo C, usted sabe mejor que inicializar una variable con un valor.
  • ummmm qué? El de arriba es solo para conseguir la pregunta de todo.
  • Son sólo preocupado acerca de enteros, o se tiene que hacer lo mismo con los no-POD tipos así?
  • En realidad, yo sólo deben lidiar con la VAINA tipos (tengo un montón de datos sobre el terreno que estoy enviando a través de una red). Esperemos que no se ocupan de nada demasiado complicado.

InformationsquelleAutor Polaris878 | 2009-10-05

10 Comentarios

  1. 22

    No de la manera más óptima, pero es endian seguro.

    
    int har = 0x01010101;
    char a[4];
    a[0] = har & 0xff;
    a[1] = (har>>8)  & 0xff;
    a[2] = (har>>16) & 0xff;
    a[3] = (har>>24) & 0xff;
    • ¿Esta carrera en problemas si har es negativo? (Me Parece recordar que hay es algo extraño acerca de bitshifting y negativos enteros…)
  2. 39

    A menos que usted se preocupa por el orden de los bytes y tal, memcpy hará el truco:

    memcpy(a, &har, sizeof(har));
    ...
    memcpy(&har2, a, sizeof(har2));

    Por supuesto, no hay ninguna garantía de que sizeof(int)==4 en cualquier aplicación (y existen en el mundo real de las implementaciones para los que esto es de hecho falso).

    Escribir un bucle debería ser trivial desde aquí.

  3. 8
    #include <stdio.h>
    
    int main(void) {
        char a[sizeof(int)];
        *((int *) a) = 0x01010101;
        printf("%d\n", *((int *) a));
        return 0;
    }

    Tener en cuenta:

    Un puntero a un objeto o de tipo incompleta puede ser convertido a un puntero a una diferente
    objeto o de tipo incompleta. Si el puntero resultante no está alineado correctamente para el
    señaló a tipo, el comportamiento es indefinido.

    • El puntero puede ser convertido, pero eso no significa que se pueda anular la referencia. E. g. usted puede convertir int* a float* (no U. B.), pero tan pronto como intenta escribir nada por que float*, de llegar a U. B. Su ejemplo está bien porque la escritura a través de char* esté permitido específicamente para las Vainas, y la vida útil de la VAINA se inicia tan pronto como se asigna la memoria para ella, pero esta es la pena aclarar.
    • En realidad, lo siento, me equivoqué», y este ejemplo es todavía U. B. – en concreto, no hay ninguna garantía de que a está correctamente alineado para int. No es una garantía a la hora de asignar las matrices con new, para que estén correctamente alineados para cualquier objeto del mismo tamaño que la matriz; pero no hay tal garantía para auto o variables estáticas, o de un miembro de los campos. E. g. considere la posibilidad de declaraciones de variables locales: char c; char a[4]; – hay una buena probabilidad de que a no será atendida en un límite de 4 bytes, y en algunas arquitecturas, esto va a resultar en un accidente cuando intenta escribir en ese lugar a través de un int*.
    • Pavel, podrían aclarar a qué nos referimos con la VAINA y de la U. B.? Gracias
    • POD = Plain Old tipo de Datos y UB = un Comportamiento Indefinido.
    • El acceso a cualquier tipo de datos utilizando un puntero char está bien. Sin embargo, suponiendo que los datos apuntada por un puntero char está correctamente alineado para otro tipo de datos resulta en un comportamiento indefinido. Cualquier cosa puede suceder.
    • POD = el Viejo y simple de Datos. U. B. = Un Comportamiento Indefinido. El significado de estos dos términos están definidos con precisión en ISO C++ especificación. U. B. significa, básicamente, «cualquier cosa puede suceder, sin límites». POD significa más o menos «uno de C++ tipos primitivos como int o float, cualquier tipo de puntero, cualquier tipo enum, matriz de cualquier tipo de POD, o cualquier struct/classe/la unión se compone únicamente de los campos de la VAINA de los tipos, con los no-miembros del sector público, no hay clases base, no explícita ctors o dtors, y no virtual miembros.»
    • Es seguro asumir que el puntero esté alineado correctamente si se le asigna a la memoria como este: char* a = new char[sizeof(int)]. La resultante del bloque de memoria está garantizado para estar alineados correctamente para cualquier objeto que puede caber dentro de ese bloque – incluyendo, obviamente, un int. En una nota de lado, que vale la pena mirar cuánto engaño boost::optional tiene que hacer para conseguir la alineación a la derecha, evitando la asignación del montón: boost.org/doc/libs/1_39_0/boost/optional/optional.hpp – mira type_with_alignment plantilla…
    • Gracias, yo sé lo que decir que yo no estaba seguro de que en el acrónimos 🙂
    • Está seguro de eliminar la referencia de la escayola puntero de la UB? Estoy bastante seguro de que hay algo acerca de él sólo se comporta como si se apunta a «un objeto con un sin especificar valor de tipo T». Por otra parte, la nota en 5.3.4:10 menciona específicamente que char matrices son max alineados para permitir que «el común lenguaje de la asignación de matrices de caracteres en el que los objetos de otros tipos va a ser colocados».
    • Sólo tengo n1124.pdf (ISO/IEC 9899:TC2) y no hay ninguna sección 5.3.4 en el documento. Creo que se está refiriendo a que el estándar de C++ (deducida a partir de boost.org/doc/libs/1_40_0/libs/pool/doc/implementation/… ). En cualquier caso, no, yo no estoy seguro de si el código anterior invoca UB aunque no puedo encontrar nada en el estándar de C que garantiza que no
    • puntero se puede convertir… La siguiente línea en la Norma contradice usted instrucción: Si el puntero resultante no está alineado correctamente para la punta, el tipo, el comportamiento es indefinido. me Deja usar su ejemplo de int y float. Si no tienen la misma alineación, de acuerdo a la Norma, la conversión de las causas de la UB. Esto es debido a que, la primera regla permite la conversión, y la siguiente regla que restringe.

  4. 8
    int main() {
        typedef union foo {
            int x;
            char a[4];
        } foo;
    
        foo p;
        p.x = 0x01010101;
        printf("%x ", p.a[0]);
        printf("%x ", p.a[1]);
        printf("%x ", p.a[2]);
        printf("%x ", p.a[3]);
    
        return 0;
    }

    Tener en cuenta que el a[0] contiene el LSB y[3] sostiene que la MSB, en un little endian máquina.

    • Tu comentario acerca de la LSB y MSB sólo es cierto para little endian arquitecturas.
    • La lectura de p.a en este código invoca U. B., porque no fue precedida de una escritura a a. Cualquier conforme a los estándares de implementación de C++ legalmente se puede optimizar la distancia de la asignación a p.x completamente, y algunos lo harán.
    • Umm, sí y no. El resultado exacto es U. B., supongo, porque depende de la arquitectura de la plataforma, pero los sindicatos son una manera legal a alias de diferentes tipos y que sería muy sorprendido por un compilador que no entendemos perfectamente que p.una había sido escrito. De hecho, los sindicatos son el solo de manera oficial todo tipo de suavizado de optimización en gnu implementaciones.
    • Eso es cierto, supongo, pero los sindicatos no son la única manera de resolver este problema, y hay soluciones que no invocar la UB, así que probablemente es mejor a favor de aquellos.
    • No es legal alias cualquiera de los dos tipo arbitrario (sindicatos o no – solo no hagas esto, período), pero es perfectamente legal alias cualquier tipo de POD a través de un char*, y g++ admite que así. La única salvedad es que para ser estrictamente conformes, debe static_cast a char* en lugar de reinterpret_cast o estilo C cast (lo que significa que primero debe static_cast a void*) – aunque no he visto ninguna aplicación cuando se que el último bit en realidad hace la diferencia…
    • En realidad, sólo por el bien de la integridad – es legal el alias de dos POD structs en un sindicato si tienen una «secuencia» de los campos (es decir, los mismos tipos en el mismo orden) al principio, pero luego sólo se puede alias aquellos campos en común…
    • Por favor, mirar lo que U. B. medios. UB, por definición, no «depender». Si depende de la arquitectura de la plataforma, a continuación, no está especificado o aplicación especificada, no de la UB. Con UB, todas las apuestas están apagadas, y, como Pablo dice, el compilador sólo podría optimizar la distancia. Sé GCC concreto permite la unión truco, pero eso no lo hace oficial. Y no es la «única» manera.

  5. 8

    Nota: el Acceso a un sindicato a través de un elemento que no era el último que le asigna es un comportamiento indefinido.
    (suponiendo una plataforma donde los personajes son 8bits y enteros de 4 bytes)
    Una máscara de bits de 0xFF máscara fuera un personaje tan

    char arr[4];
    int a = 5;
    
    arr[3] = a & 0xff;
    arr[2] = (a & 0xff00) >>8;
    arr[1] = (a & 0xff0000) >>16;
    arr[0] = (a & 0xff000000)>>24;

    haría arr[0] pulsado el byte más significativo y arr[3] pulsado el menos.

    edit:Justo lo que entiendo el truco & es poco sabio ‘y’ donde, como && es lógico «y».
    Gracias a los comentarios acerca de los olvidados cambio.

    • +1, que es el camino a seguir si una determinada representación binaria es necesario (es decir, no LSB/MSB confusión).
    • No te olvides de cambio!
    • Como se ha señalado por Polaris878, el pasado 3 de las asignaciones se establece el ‘0’ en la matriz, ya que no se usa «>>» en los valores.
  6. 7

    No utilice los sindicatos, Pavel aclara:

    Es U. B., debido a que C++ prohíbe
    el acceso a cualquier miembro de la unión distinto
    el último que se ha escrito. En
    en particular, el compilador es gratis
    optimizar la distancia de la asignación a int
    miembro por completo con el código
    anteriormente, ya que su valor no es
    posteriormente utilizados (sólo se ve la
    lectura posterior para la char[4]
    miembro, y no tiene la obligación de
    proporcionar ningún valor significativo existen).
    En la práctica, g++, en particular, es
    conocido por tirar de estos trucos, por lo que este
    no es sólo la teoría. Por otro lado,
    el uso de static_cast<void*> seguido por
    static_cast<char*> está garantizado
    trabajo.

    – Pavel Minaev

    • Es U. B., debido a que C++ prohíbe el acceso a cualquier miembro de la unión que no sea el último que se ha escrito. En particular, el compilador es gratuito para optimizar la distancia de la asignación a int miembro por completo con el código anterior, ya que su valor no es utilizado posteriormente (sólo se ve la lectura posterior de la char[4] miembro, y no tiene obligación alguna de proporcionar valor significativo existen). En la práctica, g++, en particular, es conocido por tirar como trucos, así que esto no es sólo teoría. Por otro lado, el uso de static_cast<void*> seguido por static_cast<char*> está garantizado para trabajar.
    • El pensamiento es así, yo nunca lo aclararon, sin embargo. Si no te importa, voy a dejar tu comentario como asesoramiento.
    • No me importa, pero sería bueno para corregir esos static_casts 🙂
    • Revisión gustaría. [15char]
  7. 2
     
    #include <stdint.h> 
    
    int main(int argc, char* argv[]) { 
    /* 8 enteros en un bucle */
    int i; 
    int* intPtr 
    int intArr[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 
    char* charArr = malloc(32); 
    
    for (i = 0; i < 8; i++) { 
    intPtr = (int*) &(charArr[i * 4]); 
    /* ^ ^ ^ ^ */
    /* punto | | | */
    /* fundición como int* | | */
    /* Dirección | */
    /* Ubicación en la matriz de char */
    
    *intPtr = intArr[i]; /* escribir int en la ubicación señalada */
    } 
    
    /* Leer enteros de salida */
    for (i = 0; i < 8; i++) { 
    intPtr = (int*) &(charArr[i * 4]); 
    intArr[i] = *intPtr; 
    } 
    
    char* myArr = malloc(13); 
    int myInt; 
    uint8_t* p8; /* 8 bits sin signo entero */
    uint16_t* p16; /* 16 bits sin signo entero */
    uint32_t* p32; /* sin signo de 32 bits entero */
    
    /* El uso de tamaños distintos de 4 bytes enteros, */
    /* conjunto de todos los bits en myArr 1 */
    p8 = (uint8_t*) &(myArr[0]); 
    p16 = (uint16_t*) &(myArr[1]); 
    p32 = (uint32_t*) &(myArr[5]); 
    *p8 = 255; 
    *p16 = 65535; 
    *p32 = 4294967295; 
    
    /* Obtener los valores de salida */
    p16 = (uint16_t*) &(myArr[1]); 
    uint16_t my16 = *p16; 
    
    /* Poner los 16 bits int en un regular int */
    myInt = (int) my16; 
    
    } 
    
    
  8. 1
    char a[10];
    int i=9;
    
    a=boost::lexical_cast<char>(i)

    encontrado que esta es la mejor manera de convertir char a int y vice-versa.

    alternativa a boost::lexical_cast es sprintf.

    char temp[5];
    temp[0]="h"
    temp[1]="e"
    temp[2]="l"
    temp[3]="l"
    temp[5]='
    char temp[5];
    temp[0]="h"
    temp[1]="e"
    temp[2]="l"
    temp[3]="l"
    temp[5]='\0'
    sprintf(temp+4,%d",9)
    cout<<temp;
    '
    sprintf(temp+4,%d",9) cout<<temp;

    salida sería :hell9

  9. 0
    de la unión de valor { 
    int i; 
    char bytes[sizof(int)]; 
    }; 
    
    el valor de v; 
    v. i = 2; 
    
    char* bytes = v. bytes; 
    
    • La adición de algunos explicación a su respuesta ayuda a entender lector.

Dejar respuesta

Please enter your comment!
Please enter your name here