Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.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 交错4字节整数到8字节整数_C_Bit Manipulation_Interleave - Fatal编程技术网

C 交错4字节整数到8字节整数

C 交错4字节整数到8字节整数,c,bit-manipulation,interleave,C,Bit Manipulation,Interleave,我目前正在创建一个函数,它接受两个4字节的无符号整数,并返回一个8字节的无符号长整数。我曾试图以所描述的方法为基础进行工作,但我所有的尝试都没有成功。我使用的具体输入是:0x12345678和0xdeadbeef,我要查找的结果是0x12de34ad56be78ef。这是我迄今为止的工作: unsigned long interleave(uint32_t x, uint32_t y){ uint64_t result = 0; int shift = 33; for(

我目前正在创建一个函数,它接受两个4字节的无符号整数,并返回一个8字节的无符号长整数。我曾试图以所描述的方法为基础进行工作,但我所有的尝试都没有成功。我使用的具体输入是:
0x12345678
0xdeadbeef
,我要查找的结果是
0x12de34ad56be78ef
。这是我迄今为止的工作:

unsigned long interleave(uint32_t x, uint32_t y){
    uint64_t result = 0;
    int shift = 33;

    for(int i = 64; i > 0; i-=16){
        shift -= 8;
        //printf("%d\n", i);
        //printf("%d\n", shift);
        result |= (x & i) << shift;
        result |= (y & i) << (shift-1);
    }
}
输入初始化如下:

uint32_t x = 0x12345678;
uint32_t y = 0xdeadbeef;

在此主题上的任何帮助都将不胜感激,C语言对我来说是一门非常困难的语言,位运算更是如此。

您可以这样做:

uint64_t interleave(uint32_t x, uint32_t y)
{
     uint64_t z;

     unsigned char *a = (unsigned char *)&x;   // 1
     unsigned char *b = (unsigned char *)&y;   // 1
     unsigned char *c = (unsigned char *)&z;

     c[0] = a[0];
     c[1] = b[0];
     c[2] = a[1];
     c[3] = b[1];
     c[4] = a[2];
     c[5] = b[2];
     c[6] = a[3];
     c[7] = b[3];

     return z;
}
根据订购要求,在标有
1
的行上交换
a
b

带有移位的版本,其中
y
的LSB始终是输出的LSB,如您的示例所示,是:

uint64_t interleave(uint32_t x, uint32_t y)
{
     return 
           (y & 0xFFull)
         | (x & 0xFFull)       << 8
         | (y & 0xFF00ull)     << 8
         | (x & 0xFF00ull)     << 16
         | (y & 0xFF0000ull)   << 16
         | (x & 0xFF0000ull)   << 24
         | (y & 0xFF000000ull) << 24
         | (x & 0xFF000000ull) << 32;
}
uint64\u t交织(uint32\u t x,uint32\u t y)
{
回来
(y&0xFFull)

|(x&0xFFull)您可以这样做:

uint64_t interleave(uint32_t x, uint32_t y)
{
     uint64_t z;

     unsigned char *a = (unsigned char *)&x;   // 1
     unsigned char *b = (unsigned char *)&y;   // 1
     unsigned char *c = (unsigned char *)&z;

     c[0] = a[0];
     c[1] = b[0];
     c[2] = a[1];
     c[3] = b[1];
     c[4] = a[2];
     c[5] = b[2];
     c[6] = a[3];
     c[7] = b[3];

     return z;
}
根据订购要求,在标有
1
的行上交换
a
b

带有移位的版本,其中
y
的LSB始终是输出的LSB,如您的示例所示,是:

uint64_t interleave(uint32_t x, uint32_t y)
{
     return 
           (y & 0xFFull)
         | (x & 0xFFull)       << 8
         | (y & 0xFF00ull)     << 8
         | (x & 0xFF00ull)     << 16
         | (y & 0xFF0000ull)   << 16
         | (x & 0xFF0000ull)   << 24
         | (y & 0xFF000000ull) << 24
         | (x & 0xFF000000ull) << 32;
}
uint64\u t交织(uint32\u t x,uint32\u t y)
{
回来
(y&0xFFull)

|(x&0xFFull),具有位移位和位操作(与端点无关):

uint64\u t交织(uint32\u t x,uint32\u t y){
uint64_t结果=0;
对于(uint8_t i=0;i<4;i++){

结果|=((x&(0xFFull)具有位移位和位运算(与端点无关):

uint64\u t交织(uint32\u t x,uint32\u t y){
uint64_t结果=0;
对于(uint8_t i=0;i<4;i++){

结果|=((x&(0xFFull使用联合双关。编译器易于优化

#include <stdio.h>
#include <stdint.h>
#include <string.h>

typedef union
{
        uint64_t u64;
        struct 
        {
            union
            {
                uint32_t a32;
                uint8_t a8[4]
            };
            union
            {
                uint32_t b32;
                uint8_t b8[4]
            };
        };
        uint8_t u8[8];
}data_64;

uint64_t interleave(uint32_t a, uint32_t b)
{
    data_64 in , out;

    in.a32 = a;
    in.b32 = b;



    for(size_t index = 0; index < sizeof(a); index ++)
    {

        out.u8[index * 2 + 1] = in.a8[index];
        out.u8[index * 2 ] = in.b8[index];
    }
    return out.u64;
}


int main(void)
{

    printf("%llx\n", interleave(0x12345678U, 0xdeadbeefU)) ;
}
#包括
#包括
#包括
typedef联合
{
uint64_t u64;
结构
{
协会
{
uint32_t a32;
uint8_t a8[4]
};
协会
{
uint32_t b32;
uint8_t b8[4]
};
};
uint8_t u8[8];
}数据单元64;
uint64\u t交织(uint32\u t a,uint32\u t b)
{
数据_64输入、输出;
in.a32=a;
in.b32=b;
对于(大小索引=0;索引
使用联合双关。便于编译器优化

#include <stdio.h>
#include <stdint.h>
#include <string.h>

typedef union
{
        uint64_t u64;
        struct 
        {
            union
            {
                uint32_t a32;
                uint8_t a8[4]
            };
            union
            {
                uint32_t b32;
                uint8_t b8[4]
            };
        };
        uint8_t u8[8];
}data_64;

uint64_t interleave(uint32_t a, uint32_t b)
{
    data_64 in , out;

    in.a32 = a;
    in.b32 = b;



    for(size_t index = 0; index < sizeof(a); index ++)
    {

        out.u8[index * 2 + 1] = in.a8[index];
        out.u8[index * 2 ] = in.b8[index];
    }
    return out.u64;
}


int main(void)
{

    printf("%llx\n", interleave(0x12345678U, 0xdeadbeefU)) ;
}
#包括
#包括
#包括
typedef联合
{
uint64_t u64;
结构
{
协会
{
uint32_t a32;
uint8_t a8[4]
};
协会
{
uint32_t b32;
uint8_t b8[4]
};
};
uint8_t u8[8];
}数据单元64;
uint64\u t交织(uint32\u t a,uint32\u t b)
{
数据_64输入、输出;
in.a32=a;
in.b32=b;
对于(大小索引=0;索引
这可以基于,但跳过一些步骤,因此它只交错字节。相同的想法:首先在两个步骤中展开字节,然后合并它们

以下是我的计划,用我惊人的手绘技巧来说明:

在C中(未测试):

这可以基于,但跳过一些步骤,所以它只交错字节。相同的想法:首先在几个步骤中展开字节,然后合并它们

以下是我的计划,用我惊人的手绘技巧来说明:

在C中(未测试):



与此相关,了解您为什么不使用
std::您是否需要使用
%lx
来打印无符号长字符可能会有教育意义。您的
i
值不是正确的掩码。您的移位量需要以8位的步长递减。使用内联汇编或其内部等效项:
(V)PSHUFB:uuum128i\umm\u shuffle\uepi8(uuum128i a,uuum128i b)
result
没有初始值。如果要
将内容放入其中,则需要首先确保它为空。(
result=0;
)与此相关,了解您为什么不使用
std::您是否需要使用
%lx
来打印无符号长字符可能会有教育意义。您的
i
值不是正确的掩码。您的移位量需要以8位的步长递减。使用内联汇编或其内部等效项:
(V)PSHUFB:uuum128i\umm\u shuffle\uepi8(uuum128i a,uuum128i b)
result
没有初始值。如果要
将内容放入其中,则需要首先确保它为空。(
result=0;
)这返回
0x56ffef
Hm,很奇怪。在我的机器上运行良好。也测试了它。@PhilipDiSarro添加了一种使用指针的方法,类似于其他答案之一,但使用for循环。测试了它。后一个代码通过
uint8_t
别名,取决于字节顺序。您的第一个答案需要将
结果初始化为零e> 。这返回
0x56ffef
Hm,很奇怪。在我的机器上运行良好。也测试了它。@PhilipDiskarro添加了一种使用指针的方法,类似于其他答案之一,但使用了for循环。测试了它。后一个代码通过
uint8_t
别名,取决于字节顺序。您的第一个答案需要将
结果初始化为零。第一个版本取决于机器是big-endian还是little-endian。第二个版本返回
0x56be78ef
,这是我所需输出的最后一半,我试图扩展
// step 1, moving the top two bytes
uint64_t a = (((uint64_t)x & 0xFFFF0000) << 16) | (x & 0xFFFF);
// step 2, moving bytes 2 and 6
a = ((a & 0x00FF000000FF0000) << 8) | (a & 0x000000FF000000FF);
// same thing with y
uint64_t b = (((uint64_t)y & 0xFFFF0000) << 16) | (y & 0xFFFF);
b = ((b & 0x00FF000000FF0000) << 8) | (b & 0x000000FF000000FF);
// merge them
uint64_t result = (a << 8) | b;
uint64_t interleave(uint32_t x, uint32_t y) {
  __m128i xvec = _mm_cvtsi32_si128(x);
  __m128i yvec = _mm_cvtsi32_si128(y);
  __m128i interleaved = _mm_unpacklo_epi8(yvec, xvec);
  return _mm_cvtsi128_si64(interleaved);
}