memcpy - 将uint64复制到char *

时间:2011-10-18 03:06:13

标签: c++ c

我只是不知道memcpy的工作原理。您只需复制粘贴代码,看看输出如何不加起来。我知道我可以用其他方式编写代码,但我只是想知道为什么memcpy不起作用。

typedef unsigned char* bitmap;
#define getbit(n,bmp) ((bmp[(n)>>3])&(0x80>>((n)&0x07)))
#define setbit(n,bmp) {bmp[(n)>>3]|=(0x80>>((n)&0x07));}
#define bitmapsize(n) (((int)(n)+7)>>3)
#define to_uint64(buffer,n) ((uint64_t)buffer[n] << 56 | (uint64_t)buffer[n+1] << 48 | (uint64_t)buffer[n+2] << 40  | (uint64_t)buffer[n+3] << 32 | (uint64_t) buffer[n+4] << 24 | (uint64_t)buffer[n+5] << 16 | (uint64_t)buffer[n+6] << 8  | (uint64_t)buffer[n+7])

int main(int argc, char *argv[])
{
    bitmap bm1, bm2,bm3;
    unsigned int m_size=128;

    if (!(bm1 = (bitmap) calloc (bitmapsize(m_size), sizeof(char))));             
    setbit(100,bm1);     

    if (!(bm2 = (bitmap) calloc (bitmapsize(m_size), sizeof(char))));
    setbit(120,bm2);     

    for (unsigned int i = 0; i < bitmapsize(m_size)/sizeof(uint64_t); i++)
    {
            uint64_t or_res = (to_uint64(bm2, i * sizeof(uint64_t))) | (to_uint64(bm1, i * sizeof(uint64_t)));
            std::cout<<std::bitset<64>(or_res)<<" ";
            memcpy(bm1 + i * sizeof(uint64_t), &or_res, sizeof(uint64_t));
    }

    for (int i=0; i<m_size;i++)
            if (getbit(i,bm1))   std::cout<<i<<"  ";
    std::cout<<std::endl;
    free(bm1);
    free(bm2);
    return 0;
 }

输出: 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000010000000000000000000000010000000

64 92

数字应该只是100 120,但它们不是!

1 个答案:

答案 0 :(得分:6)

我相信你有一个关于字节序的问题。当您将缓冲区转换为uint64_t时,您将缓冲区转换为小端uint64_t。因此,您的字节将按如下顺序排序:

buffer:   | char 0 | char 1 | char 2 | ... | char n
uint64_t: | byte 8 | byte 7 | byte 6 | ... | byte 0

然后你将这个uint64_t直接复制到你的缓冲区中,这样你的字节就被错误地排序了。

最简单的解决方法是更改​​to_uint64宏:

#define to_uint64(buffer,n) ((uint64_t)buffer[n+7] << 56 | (uint64_t)buffer[n+6] << 48 | (uint64_t)buffer[n+5] << 40  | (uint64_t)buffer[n+4] << 32 | (uint64_t) buffer[n+3] << 24 | (uint64_t)buffer[n+2] << 16 | (uint64_t)buffer[n+1] << 8  | (uint64_t)buffer[n])

但是,如果您尝试在大端机器上使用代码,这将给您带来问题。

实际上,更好的方法是使用:

#define to_uint64(buffer,n) (*(uint64_t*)(buffer + n))

编辑:我更改了上面的宏,因为caf指出我不需要将uint64_t置于uint64_t。宏的工作方式是将缓冲区指针(unsinged char *)转换为uint64_t指针,然后取消引用它。