c语言long unsigned int,关于c ++:如何安全地将unsigned long int转换为int?

我有一个应用程序,它以unsigned long int s的形式创建唯一的ID。 该应用程序需要这种精度。

但是,我必须以仅允许int的协议发送这些ID。 协议的接收应用程序不需要这种精度。 所以我的问题是:如何将unsigned long int转换为int,尤其是当unsigned long int大于int时?

编辑:

该协议仅支持int。 我很想知道如何避免"翻滚问题"

发送消息的应用程序需要长时间了解唯一性,而接收方仅需要在短时间内就知道唯一性。

(int)anUnsignedLong够了吗?

是吗?我不知道 :)

适当的类型转换应该可以解决问题。

将其转换为浮点数以发送它,然后又返回另一端的无符号长整数?您将失去精度,但是可以避免任何奇怪的翻转问题。如果大小不成问题,将其作为字符串发送吗?

如果id为> max ,则将获得一个"随机"数字。很难确定这是否会对您造成问题-多少取决于接收器...

为什么要投下反对票?评论?

@tcaswell,谢谢。翻车问题是我一直担心的问题。听起来不错

@Ross:可能的原因是这个问题很模糊并且依赖于外部代码-您未显示...

协议将ID用作什么?

@ MFH我正在通过OSC协议将该值发送到仅支持int的硬件。您回答了以下问题:"您将获得一个"随机"数字"

这个问题太含糊,无法有意义地回答。"转换"是什么意思?您了解long int的范围大于int的范围,这意味着通常情况下该值将被更改。那么,您如何更改它?从您的问题看来,您似乎并不真正在乎结果价值。如果是这样,那么您可以简单地通过协议发送0,而无需进行转换。但是实际上您在乎发送的价值,因此您必须提供更多详细信息。转换后您想获得什么?如何处理不适合的价值观?

@AndreyT对不起,您是正确的。我希望对ID保持一些唯一性。我希望我的上一次编辑可以解释这一点。

如果协议不需要更大的范围,为什么要使用该应用程序?

这是三年前的事,但正如您所问,这些ID是由应用程序中的一个库生成的。

这是一种可能的方法:

#include

unsigned long int uid = ...;

int abbreviated_uid = uid & INT_MAX;

例如,如果int是32位,则将丢弃UID的所有低位31位。它只会产生非负值。

这会丢失原始uid中的信息,但是您表示这不是问题。

但是您的问题很模糊,很难说这是否适合您的目的。

抱歉,含糊不清。发送消息的应用程序需要长时间了解唯一性,而接收方仅需要在短时间内就知道唯一性。

仅当需要确保abbreviated_uid为非负值时,才需要Keith Thompson的"&INT_MAX"。如果这不是问题,并且您可以容忍负ID,则简单的类型转换(C样式或static_cast())就足够了,其好处是,如果sizeof(unsigned long int)==sizeof(int),则二进制表示形式在两端都是相同的(如果在接收端将其投射回unsigned long int,则该值将与发送端相同。

接收方是否将有关ID的响应发送回发送方,并且原始发送方(现在是响应的接收方)是否需要将其与原始unsigned long int ID匹配?如果是这样,您将需要一些其他逻辑来将响应与原始ID相匹配。如果是这样,请发表表明此类要求的编辑,而我(或其他人)可以建议解决该问题的方法。解决该问题的一种可能的方法是将ID分解为多个int件,并在另一端将其重构为完全相同的unsigned long int值。如果您需要帮助,我或其他人可以帮助您。

顺便说一句,即使类型大小相同,实际上也不能保证在转换无符号long-> int之后,位表示形式是相同的。不过,在所有有用的C ++实现中它可能都是正确的。

@SteveJessop-从纯粹的角度来看,我对此没有争议。从理论上讲,C ++实现可以以不适合在本机硬件平台上直接进行计算的方式表示整数,但是这样的效率非常低,因此我认为在几乎所有情况下,这都是处理器(CPU)以及如何处理的问题。它存储有符号和无符号整数。我曾在许多2的补码系统上工作,其中在有符号和无符号之间强制转换大小相同的整数不会更改其二进制表示形式,而只会更改其解释方式。 ....

...我从未在具有其他表示形式(符号和大小,1的补全,...)的系统上工作过,但我猜测转换方式相似;即,只需更改二进制值的解释方式,因为正值与2的补全一样,无论是解释为有符号还是无符号,都具有相同的表示形式。您曾经在非2’s-compl系统上工作吗?

不,我没有。我可以认为它做任何不同的唯一实际原因是在符号幅度系统上,其中负零是陷阱表示,(unsigned long)INT_MAX+1必须转换为其他值,并且对于与ULONG_MAX的1s补码相同。 。

Boost具有numeric_cast:

unsigned long l = ...;

int i = boost::numeric_cast(l);

如果转换将溢出,则将引发异常,这可能是您想要的,也可能不是您想要的。

如您所知,理论上一般情况下不能安全地将unsigned long int转换为int。但是,确实可以在许多实用的实际情况下这样做,其中整数不是太大。

我可能会定义和使用:

struct Exc_out_of_range {};

int make_int(const unsigned long int a) {

const int n = static_cast(a);

const unsigned long int a2 = static_cast(n);

if (a2 != a) throw Exc_out_of_range();

return n;

}

当然,可以使用标头的等效解决方案,但我不知道它比上面的方法更好。 (如果代码处于时间紧迫的循环中,并且不考虑可移植性,那么您可以在汇编中进行编码,直接测试感兴趣的位,但是除非以汇编语言进行练习,否则将很麻烦。)

关于性能,值得注意的是-除非您的编译器很老-除非使用throw,否则不会增加运行时负担。

@GManNickG添加了从std::exception继承的建议。我个人对此没有强烈的感觉,但是该建议是有根据的,值得赞赏,我几乎没有理由不遵循它。您可以在此处阅读有关此类继承的更多信息。

不要创建不从std::exception继承的异常类型。在这种情况下,您可能还是要std::domain_error。

我之所以这样,是因为我必须要有一个解决方案,即使在潜在的信息丢失时,也可以将较大的整数类型转换为较小的类型。

我使用模板提出了一个非常简洁的解决方案:

template

Tout toInt(Tin in)

{

Tout retVal = 0;

if (in > 0)

retVal = static_cast(in & std::numeric_limits::max());

else if (in < 0)

retVal = static_cast(in | std::numeric_limits::min());

return retVal;

}

您可以尝试使用std::stringstream和atoi():

#include

#include

unsigned long int a = ...;

std::stringstream ss;

ss << a;

std::string str = ss.str();

int i = atoi(str.c_str());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值