Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么调用memcpy to bool value后memcpy to int不起作用_C++ - Fatal编程技术网

C++ 为什么调用memcpy to bool value后memcpy to int不起作用

C++ 为什么调用memcpy to bool value后memcpy to int不起作用,c++,C++,当我在玩memcpy的时候,我偶然发现了一个奇怪的结果,在boolmemcpy之后,在同一个内存指针上调用的memcpy给出了意想不到的结果 我创建了一个简单的测试结构,它有一堆不同类型的变量。我将结构转换为无符号字符指针,然后使用memcpy将该指针中的数据复制到单独的变量中。我试着绕过memcpy的偏移量,将int memcpy移到bool之前(改变了teststruct的布局,使int也移到bool之前)。令人惊讶的是,换档解决了这个问题 //包含3个浮点数的简单结构 结构向量 { 浮动x

当我在玩memcpy的时候,我偶然发现了一个奇怪的结果,在boolmemcpy之后,在同一个内存指针上调用的memcpy给出了意想不到的结果

我创建了一个简单的测试结构,它有一堆不同类型的变量。我将结构转换为无符号字符指针,然后使用memcpy将该指针中的数据复制到单独的变量中。我试着绕过memcpy的偏移量,将int memcpy移到bool之前(改变了teststruct的布局,使int也移到bool之前)。令人惊讶的是,换档解决了这个问题

//包含3个浮点数的简单结构
结构向量
{
浮动x;
浮动y;
浮动z;
};
//我的测试结构
结构测试2
{
浮动a;
载体b;
布尔c;
int d;
};
int main()
{
//我在这里的堆上创建我的结构并赋值
test2*test2ptr=newtest2();
test2ptr->a=50;
test2ptr->b.x=100;
test2ptr->b.y=101;
test2ptr->b.z=102;
test2ptr->c=true;
test2ptr->d=5;
//然后将结构转换为单个字节的数组
无符号字符*数据=(无符号字符*)test2ptr;
//用于跟踪偏移的变量
无符号整数偏移量=0;
//我希望将内存复制到其中的变量
浮动a;
载体b;
布尔c;
int d;
//我在这里复制内存的顺序与在结构中定义的顺序相同
std::memcpy(&a,data,sizeof(float));
//将复制的数据大小(以字节为单位)添加到偏移量
偏移量+=sizeof(浮动);
std::memcpy(&b,数据+偏移量,sizeof(向量));
偏移量+=sizeof(矢量);
std::memcpy(&c,数据+偏移量,sizeof(bool));
偏移量+=sizeof(bool);
//这一切都有效,直到这里的结果与我分配的结果相同
//但是,int值变为83886080,而不是5
//将其移到boolmemcpy之上(也将变量移到struct中)可以解决这个问题
std::memcpy(&d,数据+偏移量,sizeof(int));
偏移量+=sizeof(int);
返回0;
}

因此,我期望d的值为5,但它变成了83886080,我认为这只是随机的未初始化内存。

bool
和随后的
int
之间显然有三个填充字节。由于对齐方面的考虑,标准允许这样做(在某些系统上,访问未在4字节边界上对齐的4字节int可能很慢或崩溃)


因此,当您执行
offset+=sizeof(bool)
时,您的增量不够。
int
后跟4个字节,而不是1。结果是
5
不是您读取的第一个字节,而是最后一个字节-您正在从
test2ptr->d
d
读取三个填充字节加上第一个填充字节。这并不是巧合,
83886080=2^24*5
(填充字节显然都是零)。

忽略结构中数据的填充

请看以下简化示例:

struct X
{
    bool b;
    int i;
}; 

int main()
{
    X x;
    std::cout << "Address of b " << (void*)(&x.b) << std::endl;
    std::cout << "Address of i " << (void*)(&x.i) << std::endl;
}
struct X
{
布尔b;
int i;
}; 
int main()
{
X;

std::cout您已经得到了所需的答案,因此我将不详细介绍。我刚刚制作了一个带有日志记录的提取函数,以便更轻松地跟踪正在发生的事情

#include <cstring>
#include <iostream>
#include <memory>

// Simple struct containing 3 floats
struct vector {
    float x;
    float y;
    float z;
};

// My test struct
struct test2 {
    float a;
    vector b;
    bool c;
    int d;
};

template<typename T>
void extract(T& dest, unsigned char* data, size_t& offset) {
    std::uintptr_t dp = reinterpret_cast<std::uintptr_t>(data + offset);
    size_t align_overstep = dp % alignof(T);

    std::cout << "sizeof " << sizeof(T) << " alignof " << alignof(T) << " data "
              << dp << " mod " << align_overstep << "\n";

    if(align_overstep) {
        size_t missing = alignof(T) - align_overstep;
        std::cout << "misaligned - adding " << missing << " to align it again\n";
        offset += missing;
    }
    std::memcpy(&dest, data + offset, sizeof(dest));
    offset += sizeof(dest);
}

int main() {
    std::cout << std::boolalpha;
    // I create my structure on the heap here and assign values
    test2* test2ptr = new test2();
    test2ptr->a = 50;
    test2ptr->b.x = 100;
    test2ptr->b.y = 101;
    test2ptr->b.z = 102;
    test2ptr->c = true;
    test2ptr->d = 5;

    // Then turn the struct into an array of single bytes
    unsigned char* data = reinterpret_cast<unsigned char*>(test2ptr);
    // Variable for keeping track of the offset
    size_t offset = 0;

    // Variables that I want the memory copied into they
    float a;
    vector b;
    bool c;
    int d;

    // I copy the memory here in the same order as it is defined in the struct
    extract(a, data, offset);
    std::cout << "a " << a << "\n";

    extract(b, data, offset);
    std::cout << "b.x " << b.x << "\n";
    std::cout << "b.y " << b.y << "\n";
    std::cout << "b.z " << b.z << "\n";

    extract(c, data, offset);
    std::cout << "c " << c << "\n";

    extract(d, data, offset);
    std::cout << "d " << d << "\n";

    std::cout << offset << "\n";

    delete test2ptr;
}

struct
字段并不总是紧密打包的。它们之间可能有填充。您可以使用offsetof()来获取结构中字段的正确偏移量。我比较了手动添加sizeof得到的最终偏移量和添加offsetoff得到的偏移量,差值为21(sizeof)到40(offsetof),为什么这里有19字节的间隙?所有这些“使用指针在结构中导航”如果你得到了正确的偏移,你就可以在同一标准布局类型的对象之间进行MeMcPy,而不是C和C++中的代码> 2 ^ 24 < /C>。为什么你不准确地说“代码> 0x0500万< /代码>?
sizeof 4 alignof 4 data 12840560 mod 0
a 50
sizeof 12 alignof 4 data 12840564 mod 0
b.x 100
b.y 101
b.z 102
sizeof 1 alignof 1 data 12840576 mod 0
c true
sizeof 4 alignof 4 data 12840577 mod 1
misaligned - adding 3 to align it again
d 5
24