如何将两个32位整数组合成一个64位整数?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何将两个32位整数组合成一个64位整数?相关的知识,希望对你有一定的参考价值。

我有一个计数寄存器,它由两个32位无符号整数组成,一个用于值的高32位(最高有效字),另一个用于值的低32位(最低有效字)。

在C中组合这两个32位无符号整数然后显示为大数的最佳方法是什么?

具体来说:

leastSignificantWord = 4294967295; //2^32-1

printf("Counter: %u%u", mostSignificantWord,leastSignificantWord);

这打印很好。

当数字增加到4294967296时,我有它,所以最少有意思的W擦除为0,而且最重要的是Word(最初为0)现在为1.整个计数器现在应该读取4294967296,但是现在它只读取10,因为我只是连接1个来自最重要的词,0个来自最不重要的词。

我怎么能让它显示4294967296而不是10?

答案
long long val = (long long) mostSignificantWord << 32 | leastSignificantWord;
printf( "%lli", val );
另一答案

在这种情况下,使用具有显式大小的无符号整数可能是有利的:

#include <stdio.h>
#include <inttypes.h>

int main(void) {
  uint32_t leastSignificantWord = 0;
  uint32_t mostSignificantWord = 1;
  uint64_t i = (uint64_t) mostSignificantWord << 32 | leastSignificantWord;
  printf("%" PRIu64 "\n", i);

  return 0;
}
Output

4294967296

Break down of (uint64_t) mostSignificantWord << 32 | leastSignificantWord

  • (typename)在C中执行typecasting。它将值数据类型更改为typename。 (uint64_t)0x00000001 - > 0x0000000000000001
  • <<left shift。在C中左移无符号整数执行logical shift。 0x0000000000000001 << 32 - > 0x0000000100000000

  • |'bitwise or'(操作数的位逻辑OR)。 0b0101 | 0b1001 - > 0b1101
另一答案

我的看法:

unsigned int low = <SOME-32-BIT-CONSTRANT>
unsigned int high = <SOME-32-BIT-CONSTANT>

unsigned long long data64;

data64 = (unsigned long long) high << 32 | low;

printf ("%llx\n", data64); /* hexadecimal output */
printf ("%lld\n", data64); /* decimal output */

另一种方法:

unsigned int low = <SOME-32-BIT-CONSTRANT>
unsigned int high = <SOME-32-BIT-CONSTANT>

unsigned long long data64;
unsigned char * ptr = (unsigned char *) &data;

memcpy (ptr+0, &low, 4);
memcpy (ptr+4, &high, 4);

printf ("%llx\n", data64); /* hexadecimal output */
printf ("%lld\n", data64); /* decimal output */

两个版本都可以工作,并且它们具有相似的性能(编译器将优化memcpy)。

第二个版本不适用于big-endian目标,但是如果常量32应该是32或32ull,则它需要猜测工作。当我看到常数大于31的变换时,我无法确定。

另一答案

当upper32和lower32都为负数时,此代码有效:

data64 = ((LONGLONG)upper32<< 32) | ((LONGLONG)lower32& 0xffffffff);
另一答案

我经常以十六进制打印,而不是尝试打印小数。

因此......

printf ("0x%x%08x\n", upper32, lower32);

或者,根据架构,平台和编译器,有时你可以逃脱...

printf ("%lld\n", lower32, upper32);

要么

printf ("%lld\n", upper32, lower32);

但是,这种替代方法非常依赖于机器(endian-ness,以及64 vs 32 bit,......),一般不推荐使用。

希望这可以帮助。

另一答案

您可以通过将32位值写入内存中的正确位置来实现:

unsigned long int data64;
data64=lowerword
*(&((unsigned int)data64)+1)=upperword;

这与机器有关,但是,例如它在大端处理器上无法正常工作。

另一答案

在游戏的后期,但我需要这样的东西,类似于在32位嵌入式环境中表示64位整数的数字base10字符串。

所以,在http://mathforum.org/library/drmath/view/55970.html的启发下,我写了这个代码,可以做问题中提出的问题,但不限于base10:可以转换为2到10的任何基数,并且可以很容易地扩展到基数N.

void stringBaseAdd(char *buf, unsigned long add, int base){

    char tmp[65], *p, *q;
    int l=strlen(buf);
    int da1, da2, dar;
    int r;

    tmp[64]=0;
    q=&tmp[64];
    p=&buf[l-1];
    r=0;
    while(add && p>=buf){

        da1=add%base;
        add/=base;
        da2=*p-'0';
        dar=da1+da2+r;

        r=(dar>=base)? dar/base: 0;
        *p='0'+(dar%base);
        --p;
    }

    while(add){

        da1=add%base;
        add/=base;
        dar=da1+r;

        r=(dar>=base)? dar/base: 0;
        --q;
        *q='0'+(dar%base);
    }

    while(p>=buf && r){

        da2=*p-'0';
        dar=da2+r;

        r=(dar>=base)? 1: 0;
        *p='0'+(dar%base);
        --p;
    }

    if(r){

        --q;
        *q='0'+r;
    }

    l=strlen(q);
    if(l){

        memmove(&buf[l], buf, strlen(buf)+1);
        memcpy(buf, q, l);
    }
}
void stringBaseDouble(char *buf, int base){

    char *p;
    int l=strlen(buf);
    int da1, dar;
    int r;

    p=&buf[l-1];
    r=0;
    while(p>=buf){

        da1=*p-'0';
        dar=(da1<<1)+r;

        r=(dar>=base)? 1: 0;
        *p='0'+(dar%base);
        --p;
    }

    if(r){

        memmove(&buf[1], buf, strlen(buf)+1);
        *buf='1';
    }
}
void stringBaseInc(char *buf, int base){

    char *p;
    int l=strlen(buf);
    int da1, dar;
    int r;

    p=&buf[l-1];
    r=1;
    while(p>=buf && r){

        da1=*p-'0';
        dar=da1+r;

        r=(dar>=base)? 1: 0;
        *p='0'+(dar%base);
        --p;
    }

    if(r){

        memmove(&buf[1], buf, strlen(buf)+1);
        *buf='1';
    }
}
void stringLongLongInt(char *buf, unsigned long h, unsigned long l, int base){

    unsigned long init=l;
    int s=0, comb=0;

    if(h){

        comb=1;
        init=h;
        while(!(init&0x80000000L)){

            init<<=1;
            init|=(l&0x80000000L)? 1: 0;
            l<<=1;
            s++;
        }
    }

    buf[0]='0';
    buf[1]=0;
    stringBaseAdd(buf, init, base);

    if(comb){

        l>>=s;
        h=0x80000000L>>s;
        s=sizeof(l)*8-s;
        while(s--){

            stringBaseDouble(buf, base);
            if(l&h)
                stringBaseInc(buf, base);

            h>>=1;
        }
    }
}

如果你要求

char buff[20];
stringLongLongInt(buff, 1, 0, 10);

你的buff将包含4294967296

以上是关于如何将两个32位整数组合成一个64位整数?的主要内容,如果未能解决你的问题,请参考以下文章

使用 32 位无符号整数乘以 64 位数字的算法

对于所有外键,如何在 SQL 中将数据类型从 32 位整数升级到 64 位整数?

如何将一个 XMM 128 位寄存器拆分为两个 64 位整数寄存器?

将 n 位从 8 位数组复制到 64 位整数?

从文件中读取 64 位整数字符串

位运算之清除特定的某几位