如何将两个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位整数?的主要内容,如果未能解决你的问题,请参考以下文章
对于所有外键,如何在 SQL 中将数据类型从 32 位整数升级到 64 位整数?