为什么在C#和C ++中输出不同?

时间:2013-02-02 12:43:17

标签: c# c++

在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的答案是第一个,所以我会将其标记为已接受的答案。其他答案也是正确的,但我不能接受多个答案:\

4 个答案:

答案 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_tuint32_tuint64_t,{ {1}}而不是。

更正了C ++代码

#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)具有不同的含义。