【问题标题】:Converting an unsigned long to 64-bit signed long in C [closed]在 C 中将无符号长整数转换为 64 位有符号长整数 [关闭]
【发布时间】:2012-12-12 04:12:29
【问题描述】:

我正在尝试从 DWORDLONG 类型(在 WIN32 中定义为无符号 64 位 int)返回类型 jlong​​(在 JNI 中定义为有符号的 64 位 long 值)。

简单的类型转换:

DWORDLONG dwl = 1000000000000;
jlong n = (jlong) dwl;

由于操作未定义而更改值。

那么如何将无符号长整数转换为有符号长整数,同时保持与之前相同的数值?

更新

看来问题的发生是因为我的测试中出现了指针取消引用错误。演员并没有改变价值。感谢所有评论/回答的人,至少现在我知道这是一个完全合法的操作。

【问题讨论】:

  • 对于 64 位有符号整数范围内的正数(并且 1E12 正好在范围内),显示的强制转换应该可以工作(但如果您添加 LL 或等效后缀会更可靠价值)。如果不是,则您的期望可能不匹配(某些不是您认为是 64 位值的 64 位),或者编译器中可能存在错误。我不确定是否还有很多其他选择。你怎么知道价值在改变?您是在 C 代码中打印它,还是在等待 Java 代码获取它?转换前是否打印了dwl
  • 有什么理由不能使用jlong
  • jint 未定义为 64 位。它被定义为 32 位:docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html 你的意思是 jlong 吗?
  • 我很抱歉。我的意思是jlong​​。我不知道我为什么输入 jint。
  • 不应该是10000000000001000000000000LL

标签: c winapi java-native-interface type-conversion


【解决方案1】:

你是如何得出演员改变价值的结论的?

只有当转换值溢出有符号的目标类型(64 位整数)时,转换才构成未定义的行为,对于 1000000000000 或“可用内存量”都不应该发生这种情况(并且在运行时保护了病态情况-时间使用if (dwl > JLONG_MAX) raise_error())。我的猜测是您误解了测试。常量 1000000000000 在编译时溢出 32 位 整数并编译为 -727379968。改变值的不是演员阵容,而是值一开始就损坏了。

正如 cmets 中已经建议的那样,在您的测试程序中将 1000000000000 更改为 1000000000000LL,问题就会消失。

【讨论】:

  • 将 DWORDLONG 转换为 jlong​​ 时出现问题。当我输入问题时,整个 jint 铸造只是一个错误。
  • @ghostsoldier23 您如何证明将DWORDLONG 转换为jlong 时会出现问题?因为DWORDLONG 是一个无符号的64 位整数,而jlong 是一个有符号的64 位整数,所以从DWORDLONG 转换为jlong 将适用于小于2**63 的所有值。根据当前可用的数据,您的测试程序中 1000000000000 常量的溢出似乎导致您得出错误的结论,即强制转换失败。 (这与jint 错字无关。)
  • 我确实发现了一个 DWORDLONG 值的取消引用错误。这可能产生了影响。当我有能力并发布结果时,我将再次检查 JNI 输出。
  • 好吧原来是解引用错误搞砸了一切,而不是演员表,我的测试没有显示(可能是在指针分配之前放置测试变量?)。所以这个问题就解决了。现在,如果我试图将其转换为 32 位有符号整数(不溢出),它还能工作吗?
  • @ghostsoldier23 是的,如果没有溢出,它仍然可以工作。 C 从一开始就支持这一点,并且广泛用于系统 API,例如 stdio getchar(),在检查了 EOF 特殊值之后,您应该定期将其 int 结果转换为 char
猜你喜欢
  • 1970-01-01
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
  • 2012-01-09
相关资源
最近更新 更多