在C#中
var buffer = new byte[] {71, 20, 0, 0, 9, 0, 0, 0};
var g = (ulong) ((uint) (buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24) |
(long) (buffer[4] | buffer[5] << 8 | buffer[6] << 16 | buffer[7] << 24) << 32);
在C ++中
#define byte unsigned char
#define uint unsigned int
#define ulong unsigned long long
byte buffer[8] = {71, 20, 0, 0, 9, 0, 0, 0};
ulong g = (ulong) ((uint) (buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24) |
(long) (buffer[4] | buffer[5] << 8 | buffer[6] << 16 | buffer[7] << 24) << 32);
C#输出38654710855
,C ++输出5199
。
为什么呢?几个小时以来,我一直在摸不着头......
编辑:C#输出正确。
感谢大家的帮助:) Jack Aidley的答案是第一个,所以我会将其标记为已接受的答案。其他答案也是正确的,但我不能接受多个答案:\
答案 0 :(得分:6)
C ++无法正常工作,因为您正在转换为long
,在大多数当前C ++实现中通常为32位,但其确切长度留给实现者。你想要long long
。
另外,请阅读下面的Bikeshedder更完整的答案。他是非常正确的,固定大小的typedef是一种更可靠的方法。
答案 1 :(得分:4)
问题是C++
中的long类型仍然是4字节或32位(在大多数编译器上),因此您的计算会溢出它。但是C#
long
C++
与long long
的{{1}}相同且为64位,因此表达式的结果符合该类型。
答案 2 :(得分:2)
您的unsigned long
不是64位长。您可以使用sizeof(unsigned long)
轻松检查这一点,short <= int <= long <= long long
应该返回4(= 32位)而不是8(= 64位)。
如果您希望它们具有特定大小,请不要使用int / short / long。标准只说long
并定义最小尺寸。它们实际上可以是相同的大小。保证long long
至少为32位,<cstdint.h>
保证至少为64位。 (参见Page 22 of the C++ Standard)如果你真的想要使用特定尺寸的话,我强烈建议不要这样做并坚持使用stdint。
使用<cstdint>
(C ++ 11)或uint8_t
(C ++ 98)和已定义的类型uint16_t
,uint32_t
,uint64_t
,{ {1}}而不是。
#include <stdint.h>
#include <iostream>
int main(int argc, char *argv[]) {
uint8_t buffer[8] = {71, 20, 0, 0, 9, 0, 0, 0};
uint64_t g = (uint64_t) ((uint32_t) (buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24) |
(int64_t) (buffer[4] | buffer[5] << 8 | buffer[6] << 16 | buffer[7] << 24) << 32);
std::cout << g << std::endl;
return 0;
}
使用输出进行演示:http://codepad.org/e8GOuvMp
答案 3 :(得分:1)
你的演员有一个微妙的错误。
C#中的长整数是64位整数。 C ++中的long通常是32位整数。
因此,当您在C#或C ++中执行时,(long) (buffer[4] | buffer[5] << 8 | buffer[6] << 16 | buffer[7] << 24) << 32)
具有不同的含义。