C++中是否有将字符串转换为uintptr_tintptr_t的函数(C++ 11,如果有所不同)?我总是可以使用atoll()并在之后将其强制转换,但是最好得到一个对32位计算机执行32位而对64位计算机执行64位的函数。

char* c = "1234567";
uintptr_t ptr = atoptr(c); // a function that does this;

最佳答案

这是IMO在C++中令人惊讶的差距。尽管stringstream可以完成这项工作,但对于完成这样一个简单的任务而言,它却是一个沉重的工具。相反,您可以编写一个内联函数,该函数根据类型大小调用strtoul的正确变体。由于编译器知道正确的大小,因此它将足够聪明,可以将对函数的调用替换为对strtoul或strtoull的调用。即,如下所示:

    inline uintptr_t handleFromString(const char *c, int base = 16)
    {
         // See if this function catches all possibilities.
         // If it doesn't, the function would have to be amended
         // whenever you add a combination of architecture and
         // compiler that is not yet addressed.
         static_assert(sizeof(uintptr_t) == sizeof(unsigned long)
             || sizeof(uintptr_t) == sizeof(unsigned long long),
             "Please add string to handle conversion for this architecture.");

         // Now choose the correct function ...
         if (sizeof(uintptr_t) == sizeof(unsigned long)) {
             return strtoul(c, nullptr, base);
         }

         // All other options exhausted, sizeof(uintptr_t) == sizeof(unsigned long long))
         return strtoull(c, nullptr, base);
    }
如果您决定更改手柄的类型,这将很容易更新。如果您喜欢尖括号,您也可以做一些与模板等效的操作,尽管我不认为这会更清楚。
最后,您还可以使用sscanf格式的%tx,即
inline uintptr_t handleFromString(const char *c)
{
   ptrdiff_t h;
   sscanf(c, "%tx", &h); // only hex supported, %td for decimal.
   return (uintptr_t)h;
}
不幸的是,我在Compiler Explorer上尝试过的编译器都无法以消除对sscanf的调用的方式来优化代码。

09-04 15:29