在c#中实现c++中的函数(MAKE_HRESULT - Windows函数)
Implement function from C++ in C# (MAKE_HRESULT - Windows function)
我在c++中有这样的代码
#define dppHRESULT(Code)
MAKE_HRESULT(1, 138, (Code))
long x = dppHRESULT(101);
结果为x = -2138439579.
MAKE_HRESULT
是一个窗口函数,定义为
#define MAKE_HRESULT(sev,fac,code)
((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
我需要在c#中复制这个。所以我写了这段代码:
public static long MakeHResult(uint facility, uint errorNo)
{
// Make HR
uint result = (uint)1 << 31;
result |= (uint)facility << 16;
result |= (uint)errorNo;
return (long) result;
}
和调用:
// Should return type be long actually??
long test = DppUtilities.MakeHResult(138, 101);
但我得到不同的结果,test
= 2156527717。
为什么?有人能帮我复制c++函数也在c# ?使我在相似的输入上得到相似的输出?
替代实现。
如果我使用这个实现
public static long MakeHResult(ulong facility, ulong errorNo)
{
// Make HR
long result = (long)1 << 31;
result |= (long)facility << 16;
result |= (long)errorNo;
return (long) result;
}
这适用于输入101。但是如果我输入-1,那么c++返回-1作为结果,而c#返回4294967295。为什么?
我真的很感激你的帮助,因为我被卡住了。
我已经重写了这个函数,使其与c#相同。
static int MakeHResult(uint facility, uint errorNo)
{
// Make HR
uint result = 1U << 31;
result |= facility << 16;
result |= errorNo;
return unchecked((int)result);
}
c#对有符号/无符号转换更严格,而原始的C代码没有注意到它。有符号类型和无符号类型混合使用通常会让人头疼。
正如Ben Voigt在他的回答中提到的,这两种语言在类型命名上是不同的。C中的long
实际上是c#中的int
。它们都指向32位类型。
1U
中的U表示"这是一个无符号整数"。(简单提醒一下:有符号类型可以存储负数,无符号类型不能。)这个函数中的所有算术运算都是无符号的,最后的值只是在最后转换为有符号的值。这是最接近原始C宏的方法。
unchecked
在这里是必需的,否则c#将不允许您转换值,如果它超出了目标类型的范围,即使位是相同的。如果您不介意在处理负数时值不同,则在有符号和无符号之间切换通常需要此操作。
在Windows c++编译器中,long
是32位的。在c#中,long
是64位。这段代码的c#转换不应该包含类型关键字long
。
SaxxonPike提供了正确的翻译,但他的解释遗漏了这一重要信息。
中间结果是一个32位无符号整数。在c++版本中,强制转换为带符号的32位值,导致高位被重新解释为符号位。SaxxonPike的代码也做到了这一点。如果中间值设置了最高有效位,则结果为负。
在问题的原始代码中,强制转换为64位带符号的版本,它保留旧的高位作为正常的二进制数字,并添加一个新的符号位(始终为零)。因此,结果总是肯定的。即使低32位完全匹配c++中的32位结果,在返回long
的c#版本中,c++中的符号位不被视为符号位。
在问题的新尝试中,发生了同样的事情(64位数字中的符号位始终为零),但它发生在中间计算而不是最后。
您正在unsigned类型(uint
)中计算它。所以位移会有相应的表现。试着用int
代替,看看会发生什么。
这里的线索是,作为无符号整型的2156527717与作为有符号整型的-2138439579相同。它们实际上是相同的位。
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗