在char数组中存储int ?

时间:2020-11-27 21:35:40

I want to store a 4-byte int in a char array... such that the first 4 locations of the char array are the 4 bytes of the int.

我想在char数组中存储一个4字节的int…这样,char数组的前4个位置就是int的4个字节。

Then, I want to pull the int back out of the array...

然后,我想从数组中拉出int…

Also, bonus points if someone can give me code for doing this in a loop... IE writing like 8 ints into a 32 byte array.

另外,如果有人能给我一个循环的代码,也可以加分……我把8英寸写进一个32字节的数组。

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

Thanks guys!

谢谢你们了!

EDIT: Assume int are 4 bytes...

编辑:假设int是4个字节…

EDIT2: Please don't care about endianness... I will be worrying about endianness. I just want different ways to acheive the above in C/C++. Thanks

请不要在意意外的发现……我会担心意外的发现。我只是想用不同的方法在C/ c++中完成上述任务。谢谢

EDIT3: If you can't tell, I'm trying to write a serialization class on the low level... so I'm looking for different strategies to serialize some common data types.

EDIT3:如果你看不出来,我正在尝试在底层编写一个序列化类……所以我在寻找不同的策略来序列化一些常见的数据类型。

10 个解决方案

#1


20  

Not the most optimal way, but is endian safe.

这不是最理想的方法,但恩甸是安全的。


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;

#2


39  

Unless you care about byte order and such, memcpy will do the trick:

除非你关心字节顺序之类的,否则memcpy就可以做到:

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

Of course, there's no guarantee that sizeof(int)==4 on any particular implementation (and there are real-world implementations for which this is in fact false).

当然,不能保证在任何特定的实现上sizeof(int)==4(在现实世界中有一些实现实际上是假的)。

Writing a loop should be trivial from here.

从这里编写一个循环应该是微不足道的。

#3


8  

#include <stdio.h>

int main(void) {
    char a[sizeof(int)];
    *((int *) a) = 0x01010101;
    printf("%d\n", *((int *) a));
    return 0;
}

Keep in mind:

请记住:

A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined.

指向对象或不完整类型的指针可以转换为指向不同对象或不完整类型的指针。如果结果指针没有正确对齐指向类型,则该行为未定义。

#4


8  

Note: Accessing a union through an element that wasn't the last one assigned to is undefined behavior. (assuming a platform where characters are 8bits and ints are 4 bytes) A bit mask of 0xFF will mask off one character so

注意:通过不属于最后一个元素的元素访问联合是未定义的行为。(假设平台的字符是8bit, ints是4字节

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;

would make arr[0] hold the most significant byte and arr[3] hold the least.

将使arr[0]持有最重要的字节,而arr[3]持有最少的字节。

edit:Just so you understand the trick & is bit wise 'and' where as && is logical 'and'. Thanks to the comments about the forgotten shift.

编辑:这样你就能理解这个技巧和智慧,以及“where && & is logical”和“。”多亏了关于这个被遗忘的转变的评论。

#5


7  

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;
}

Bear in mind that the a[0] holds the LSB and a[3] holds the MSB, on a little endian machine.

记住,在一个小的endian机器上,a[0]持有LSB,而[3]持有MSB。

#6


7  

Don't use unions, Pavel clarifies:

帕维尔明确表示,不要使用工会:

It's U.B., because C++ prohibits accessing any union member other than the last one that was written to. In particular, the compiler is free to optimize away the assignment to int member out completely with the code above, since its value is not subsequently used (it only sees the subsequent read for the char[4] member, and has no obligation to provide any meaningful value there). In practice, g++ in particular is known for pulling such tricks, so this isn't just theory. On the other hand, using static_cast<void*> followed by static_cast<char*> is guaranteed to work.

这是U.B.,因为c++禁止访问除最后一个被写入的union成员之外的任何union成员。特别是,编译器可以*地将赋值优化到完全与上面的代码一起,因为它的值不会随后被使用(它只看到char[4]成员的后续读取,并且没有义务提供任何有意义的值)。实际上,g++尤其擅长耍这种花招,所以这不仅仅是理论。另一方面,使用static_cast ,后跟static_cast ,保证可以工作。 *> *>

– Pavel Minaev

——帕维尔Minaev

#7


3  

You can also use placement new for this:

你也可以使用新的放置方式:

void foo (int i) {
  char * c = new (&i) char[sizeof(i)];
}

#8


1  


    #include <stdint.h>

    int main(int argc, char* argv[]) {
        /* 8 ints in a loop */
        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]);
          /*  ^            ^    ^        ^     */
          /* point at      |    |        |     */
          /*       cast as int* |        |     */
          /*               Address of    |     */
          /*            Location in char array */

            *intPtr = intArr[i]; /* write int at location pointed to */
        }

        /* Read ints out */
        for (i = 0; i < 8; i++) {
            intPtr = (int*) &(charArr[i * 4]);
            intArr[i] = *intPtr;
        }

        char* myArr = malloc(13);
        int myInt;
        uint8_t* p8;    /* unsigned 8-bit integer  */
        uint16_t* p16;  /* unsigned 16-bit integer */
        uint32_t* p32;  /* unsigned 32-bit integer */

        /* Using sizes other than 4-byte ints, */
        /* set all bits in myArr to 1          */
        p8 = (uint8_t*) &(myArr[0]);
        p16 = (uint16_t*) &(myArr[1]);
        p32 = (uint32_t*) &(myArr[5]);
        *p8 = 255;
        *p16 = 65535;
        *p32 = 4294967295;

        /* Get the values back out */
        p16 = (uint16_t*) &(myArr[1]);
        uint16_t my16 = *p16;

        /* Put the 16 bit int into a regular int */
        myInt = (int) my16;

    }

#9


1  

char a[10];
int i=9;

a=boost::lexical_cast<char>(i)

found this is the best way to convert char into int and vice-versa.

发现这是将char转换为int的最佳方式,反之亦然。

alternative to boost::lexical_cast is sprintf.

boost的替代方案::lexical_cast是sprintf。

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;

output would be :hell9

输出是:hell9

#10


0  

union value {
   int i;
   char bytes[sizof(int)];
};

value v;
v.i = 2;

char* bytes = v.bytes;

#1


20  

Not the most optimal way, but is endian safe.

这不是最理想的方法,但恩甸是安全的。


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;

#2


39  

Unless you care about byte order and such, memcpy will do the trick:

除非你关心字节顺序之类的,否则memcpy就可以做到:

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

Of course, there's no guarantee that sizeof(int)==4 on any particular implementation (and there are real-world implementations for which this is in fact false).

当然,不能保证在任何特定的实现上sizeof(int)==4(在现实世界中有一些实现实际上是假的)。

Writing a loop should be trivial from here.

从这里编写一个循环应该是微不足道的。

#3


8  

#include <stdio.h>

int main(void) {
    char a[sizeof(int)];
    *((int *) a) = 0x01010101;
    printf("%d\n", *((int *) a));
    return 0;
}

Keep in mind:

请记住:

A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined.

指向对象或不完整类型的指针可以转换为指向不同对象或不完整类型的指针。如果结果指针没有正确对齐指向类型,则该行为未定义。

#4


8  

Note: Accessing a union through an element that wasn't the last one assigned to is undefined behavior. (assuming a platform where characters are 8bits and ints are 4 bytes) A bit mask of 0xFF will mask off one character so

注意:通过不属于最后一个元素的元素访问联合是未定义的行为。(假设平台的字符是8bit, ints是4字节

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;

would make arr[0] hold the most significant byte and arr[3] hold the least.

将使arr[0]持有最重要的字节,而arr[3]持有最少的字节。

edit:Just so you understand the trick & is bit wise 'and' where as && is logical 'and'. Thanks to the comments about the forgotten shift.

编辑:这样你就能理解这个技巧和智慧,以及“where && & is logical”和“。”多亏了关于这个被遗忘的转变的评论。

#5


7  

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;
}

Bear in mind that the a[0] holds the LSB and a[3] holds the MSB, on a little endian machine.

记住,在一个小的endian机器上,a[0]持有LSB,而[3]持有MSB。

#6


7  

Don't use unions, Pavel clarifies:

帕维尔明确表示,不要使用工会:

It's U.B., because C++ prohibits accessing any union member other than the last one that was written to. In particular, the compiler is free to optimize away the assignment to int member out completely with the code above, since its value is not subsequently used (it only sees the subsequent read for the char[4] member, and has no obligation to provide any meaningful value there). In practice, g++ in particular is known for pulling such tricks, so this isn't just theory. On the other hand, using static_cast<void*> followed by static_cast<char*> is guaranteed to work.

这是U.B.,因为c++禁止访问除最后一个被写入的union成员之外的任何union成员。特别是,编译器可以*地将赋值优化到完全与上面的代码一起,因为它的值不会随后被使用(它只看到char[4]成员的后续读取,并且没有义务提供任何有意义的值)。实际上,g++尤其擅长耍这种花招,所以这不仅仅是理论。另一方面,使用static_cast ,后跟static_cast ,保证可以工作。 *> *>

– Pavel Minaev

——帕维尔Minaev

#7


3  

You can also use placement new for this:

你也可以使用新的放置方式:

void foo (int i) {
  char * c = new (&i) char[sizeof(i)];
}

#8


1  


    #include <stdint.h>

    int main(int argc, char* argv[]) {
        /* 8 ints in a loop */
        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]);
          /*  ^            ^    ^        ^     */
          /* point at      |    |        |     */
          /*       cast as int* |        |     */
          /*               Address of    |     */
          /*            Location in char array */

            *intPtr = intArr[i]; /* write int at location pointed to */
        }

        /* Read ints out */
        for (i = 0; i < 8; i++) {
            intPtr = (int*) &(charArr[i * 4]);
            intArr[i] = *intPtr;
        }

        char* myArr = malloc(13);
        int myInt;
        uint8_t* p8;    /* unsigned 8-bit integer  */
        uint16_t* p16;  /* unsigned 16-bit integer */
        uint32_t* p32;  /* unsigned 32-bit integer */

        /* Using sizes other than 4-byte ints, */
        /* set all bits in myArr to 1          */
        p8 = (uint8_t*) &(myArr[0]);
        p16 = (uint16_t*) &(myArr[1]);
        p32 = (uint32_t*) &(myArr[5]);
        *p8 = 255;
        *p16 = 65535;
        *p32 = 4294967295;

        /* Get the values back out */
        p16 = (uint16_t*) &(myArr[1]);
        uint16_t my16 = *p16;

        /* Put the 16 bit int into a regular int */
        myInt = (int) my16;

    }

#9


1  

char a[10];
int i=9;

a=boost::lexical_cast<char>(i)

found this is the best way to convert char into int and vice-versa.

发现这是将char转换为int的最佳方式,反之亦然。

alternative to boost::lexical_cast is sprintf.

boost的替代方案::lexical_cast是sprintf。

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;

output would be :hell9

输出是:hell9

#10


0  

union value {
   int i;
   char bytes[sizof(int)];
};

value v;
v.i = 2;

char* bytes = v.bytes;