[英]How can I safely convert `unsigned long int` to `int`?
我有一個應用程序,它以unsigned long int
的形式創建唯一的id 。 該應用程序需要這種精度。
但是,我必須在只允許int
的協議中發送這些id 。 接收應用程序 - 協議 - 不需要這種精度。 所以我的問題是:如何將unsigned long int
轉換為int
,尤其是當unsigned long int
大於int
?
該協議僅支持int
。 我很高興知道如何避免“翻車問題”
發送消息的應用程序需要長時間知道唯一性,而接收者只需要在很短的時間內知道唯一性。
這是一種可能的方法:
#include <climits>
unsigned long int uid = ...;
int abbreviated_uid = uid & INT_MAX;
例如,如果int
是32位,則丟棄除UID的低位31位之外的所有位。 它只會產生非負值。
這會丟失原始uid
,但您表示這不是問題。
但是你的問題很模糊,很難說這是否符合你的目的。
如你所知,一個人不能在理論上安全的轉換unsigned long int
到int
在一般情況下。 然而,在許多感興趣的實際情況中,人們確實可以這樣做,其中整數不是太大。
我可能會定義並使用它:
struct Exc_out_of_range {};
int make_int(const unsigned long int a) {
const int n = static_cast<int>(a);
const unsigned long int a2 = static_cast<unsigned long int>(n);
if (a2 != a) throw Exc_out_of_range();
return n;
}
使用<limits>
標頭的等效解決方案自然是可行的,但我不知道它比上面的更好。 (如果代碼處於時間關鍵循環並且可移植性不是一個因素,那么您可以在匯編中對其進行編碼,直接測試一些或多個感興趣的位,但除了作為匯編語言的練習外,這將是一個麻煩。)
關於性能,值得注意的是 - 除非你的編譯器很老 - 除非使用,否則throw
不會產生運行時負擔。
@GManNickG添加了從std::exception
繼承的建議。 我個人對此沒有強烈的感覺,但建議是有充分理由和贊賞的,我認為沒有理由不遵循它。 您可以在此處閱讀有關此類繼承的更多信息。
Boost有numeric_cast
:
unsigned long l = ...;
int i = boost::numeric_cast<int>(l);
如果轉換會溢出,這將拋出異常,這可能是您想要的,也可能不是。
只有在需要確保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
值。 如果您需要幫助,我或其他人可以提供幫助。
我來到這里,因為我必須有一個解決方案,將更大的整數類型轉換為更小的類型,即使可能丟失信息。
我想出了一個使用模板的非常簡潔的解決方案:
template<typename Tout, typename Tin>
Tout toInt(Tin in)
{
Tout retVal = 0;
if (in > 0)
retVal = static_cast<Tout>(in & std::numeric_limits<Tout>::max());
else if (in < 0)
retVal = static_cast<Tout>(in | std::numeric_limits<Tout>::min());
return retVal;
}
您可以嘗試使用std::stringstream
和atoi()
:
#include <sstream>
#include <stdlib.h>
unsigned long int a = ...;
std::stringstream ss;
ss << a;
std::string str = ss.str();
int i = atoi(str.c_str());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.