将size_t转换为unsigned int(来自API函数)

12
我正在使用Oracle API访问数据库,该API有一个函数readBuffer(char * buffer, unsigned int size);,但我无法对其进行任何更改。

我有一个使用此API的类,我的函数签名目前需要一个std::string和一个unsigned int作为大小参数。问题是当我将std::string.size()传递给函数的大小参数时,编译器会发出警告,提示从size_t转换为unsigned int可能会导致数据丢失。

我想知道是否有一种有效的方法size_t转换为unsigned int,以便我可以将其传递给我的API,并避免编译器发出警告?

我了解size_t的用途,并在谷歌上搜索这个转换的结果,得到很多说“将函数改为接受size_t参数”的结果,但在这种情况下,我无法更改API的签名。

您有什么建议吗?


size_t 实际上就是一个无符号整型。问题在于 size_t 的长度并没有被明确定义,如果你的系统定义它比“正常”的无符号整型有更多的位数,那么你就无法避免可能的数据丢失。当进行显式转换时,警告信息是否也会出现? - Chris
5个回答

22

是的,编写一个辅助函数来检查是否可以进行这样的转换,如果不能则抛出异常。可以像这样实现:

unsigned int convert( size_t what )
{
    if( what > UINT_MAX ) {
       throw SomeReasonableException();
    }
    return static_cast<unsigned int>( what );
}

是的,我喜欢这个想法。实际上,字符串的大小超过32位(4GB)的可能性很小,但这是一个不错的练习。 - Diego Sevilla
4
boost::numeric_cast 大体上可以实现这个功能。 - Steve Jessop

5

好的,可以使用 static_cast<unsigned int>(mystring.size())

原因是std::size_t通常是指针大小,但在一些64位平台上,int仍然是32位。在这种情况下,唯一可能造成数据丢失的原因是所涉及的字符串长度超过了2^32个字节。

如果您确定不会出现这种情况,请在某个位置放置一个assert来捕获这种情况并让编译器静音使用static_cast


4
static_cast<unsigned int>(str.size());

如果您想要谨慎:

if (static_cast<unsigned int>(str.size()) != str.size()) 
  throw ...

1

您可以使用以下方式强制转换:

static_cast<unsigned int>(your_variable)

构造。当然正确的方式是让API接受size_t...


1
这里的风险在于size_t可能比(unsigned)int大,因此如果是这种情况,您就不能安全地进行转换。

例如,可能会出现int为32位,而size_t为64位的情况。 我不知道这样的系统/配置,但它可能会发生。

对于大多数“合理”的系统,两者的长度都至少为32位,单个4 GB字符串仍然(也许)不太可能出现。

因此,您可以进行强制类型转换,这是有效的,但对于所有可能的系统和边角情况来说并不“安全”。

3
"我脑海中没有这样的系统/配置" - 64位Windows,64位Linux。 - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接