将int存储在char数组中?

Pol*_*878 20 c c++ arrays pointers

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

然后,我想把int拉出数组......

此外,如果有人可以给我代码在循环中执行此操作,奖励积分... IE写入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
Run Code Online (Sandbox Code Playgroud)

多谢你们!

编辑:假设int有4个字节......

编辑2:请不要关心字节序...我会担心字节序.我只是想用不同的方法来实现C/C++中的上述功能.谢谢

编辑3:如果你不能说,我正在尝试在低级写一个序列化类......所以我正在寻找不同的策略来序列化一些常见的数据类型.

Pav*_*aev 39

除非你关心字节顺序等等,memcpy否则会做到这一点:

memcpy(a, &har, sizeof(har));
...
memcpy(&har2, a, sizeof(har2));
Run Code Online (Sandbox Code Playgroud)

当然,并不能保证sizeof(int)==4在任何特定的实现上(并且有实际的实现,这实际上是错误的).

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


小智 22

不是最优化的方式,但是endian是安全的.


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;
Run Code Online (Sandbox Code Playgroud)


Ash*_*win 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;
}
Run Code Online (Sandbox Code Playgroud)

请记住,a [0]在一个小端机器上保存LSB而a [3]保持MSB.

  • 在这段代码中读取`pa`会调用UB,因为它之前没有写入`a`.任何符合要求的C++实现都可以合法地优化完全分配给`px`,有些人会这样做. (5认同)

Sin*_*nür 8

#include <stdio.h>

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

记住:

指向对象或不完整类型的指针可以转换为指向不同对象或不完整类型的指针.如果生成的指针未针对指向类型正确对齐,则行为未定义.

  • 指针可以转换,但这并不意味着它可以被解除引用.例如,您可以将`int*`转换为`float*`(无UB),但是只要您尝试通过`float*`编写任何内容,就可以点击UB您的示例很好,因为通过`char*`写的是具体的允许POD,POD的生命周期一旦为其分配内存就开始,但这值得澄清. (4认同)
  • 实际上,对不起,我错了,这个例子仍然是UB - 具体来说,不能保证`a`正确对齐`int`.在使用`new`分配数组时,可以保证它们可以正确地对齐任何与数组大小相同的对象; 但是对于自动或静态变量或成员字段没有这样的保证.例如,考虑局部变量声明:`char c; char a [4];` - 很可能不会在4字节边界上分配`a`,而在某些体系结构上,当你尝试通过`int*写入该位置时,这将导致崩溃`. (2认同)
  • POD =普通旧数据.UB =未定义的行为.这两个术语的含义在ISO C++规范中精确定义.UB基本上意味着"任何事都可以发生,没有限制".POD或多或少是"C++原始类型之一,如int或float,任何指针类型,任何枚举类型,任何POD类型的数组,或任何仅由POD类型字段组成的struct/classe/union,没有非公开成员,没有基类,没有明确的ctors或dtors,也没有虚拟成员." (2认同)

sto*_*tal 8

注意:通过不是最后一个元素的元素访问联合是未定义的行为.(假设字符为8位且整数为4字节的平台)0xFF的位掩码将屏蔽掉一个字符

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;
Run Code Online (Sandbox Code Playgroud)

会使arr [0]保持最重要的字节,而arr [3]保持最少.

编辑:只是让你理解这个技巧并且有点明智'和'其中&&是逻辑'和'.感谢有关遗忘转变的评论.

  • 别忘了转移! (4认同)

GMa*_*ckG 7

不要使用工会,帕维尔澄清:

这是UB,因为C++禁止访问除写入的最后一个之外的任何工会成员.特别是,编译器可以int 使用上面的代码自由地完全取消对成员的赋值,因为它的值随后不被使用(它只看到char[4] 成员的后续读取,并且没有义务在那里提供任何有意义的值) .在实践中,g ++尤其以提取这些技巧而闻名,所以这不仅仅是理论.另一方面,使用static_cast<void*>后跟 static_cast<char*>保证可以工作.

- 帕维尔·米娜耶夫