C语言 如何以快速安全的方式将十六进制字符串转换为无符号 64 位(uint64_t)整数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4132318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to convert hex string to unsigned 64bit (uint64_t) integer in a fast and safe way?
提问by Mickey Shine
I tried
我试过
sscanf(str, "%016llX", &int64 );
but seems not safe. Is there a fast and safe way to do the type casting?
但似乎不安全。有没有一种快速安全的方法来进行类型转换?
Thanks~
谢谢~
回答by R.. GitHub STOP HELPING ICE
Don't bother with functions in the scanffamily. They're nearly impossible to use robustly. Here's a general safe use of strtoull:
不要打扰scanf家庭中的功能。它们几乎不可能稳健地使用。以下是一般安全使用strtoull:
char *str, *end;
unsigned long long result;
errno = 0;
result = strtoull(str, &end, 16);
if (result == 0 && end == str) {
/* str was not a number */
} else if (result == ULLONG_MAX && errno) {
/* the value of str does not fit in unsigned long long */
} else if (*end) {
/* str began with a number but has junk left over at the end */
}
Note that strtoullaccepts an optional 0xprefix on the string, as well as optional initial whitespace and a sign character (+or -). If you want to reject these, you should perform a test before calling strtoull, for instance:
请注意,strtoull接受0x字符串上的可选前缀,以及可选的初始空格和符号字符(+或-)。如果你想拒绝这些,你应该在调用之前执行测试strtoull,例如:
if (!isxdigit(str[0]) || (str[1] && !isxdigit(str[1])))
If you also wish to disallow overly long representations of numbers (leading zeros), you could check the following condition before calling strtoull:
如果您还希望禁止过长的数字表示(前导零),您可以在调用之前检查以下条件strtoull:
if (str[0]=='0' && str[1])
One more thing to keep in mind is that "negative numbers" are not considered outside the range of conversion; instead, a prefix of -is treated the same as the unary negation operator in C applied to an unsigned value, so for example strtoull("-2", 0, 16)will return ULLONG_MAX-1(without setting errno).
要记住的另一件事是,“负数”不被考虑在转换范围之外;相反,前缀 of-被视为与 C 中应用于无符号值的一元否定运算符相同,因此例如strtoull("-2", 0, 16)将返回ULLONG_MAX-1(不设置errno)。
回答by dreamlax
Your title (at present) contradicts the code you provided. If you want to do what your title was originally (convert a string to an integer), then you can use this answer.
您的标题(目前)与您提供的代码相矛盾。如果你想做你最初的标题(将字符串转换为整数),那么你可以使用这个答案。
You could use the strtoullfunction, which unlike sscanfis a function specifically geared towards reading textual representations of numbers.
您可以使用该strtoull函数,它不同于sscanf专门用于读取数字文本表示的函数。
const char *test = "123456789abcdef0";
errno = 0;
unsigned long long result = strtoull(test, NULL, 16);
if (errno == EINVAL)
{
// not a valid number
}
else if (errno == ERANGE)
{
// does not fit in an unsigned long long
}
回答by DevSolar
At the time I wrote this answer, your title suggested you'd want to write an uint64_t into a string, while your code did the opposite (reading a hex string into an uint64_t). I answered "both ways":
在我写这个答案的时候,你的标题表明你想将一个 uint64_t 写入一个字符串,而你的代码则相反(将一个十六进制字符串读入一个 uint64_t)。我回答“双向”:
The <inttypes.h>header has conversion macros to handle the ..._ttypes safely:
该<inttypes.h>头具有转换宏来处理..._t安全类型:
#include <stdio.h>
#include <inttypes.h>
sprintf( str, "%016" PRIx64, uint64 );
Or (if that is indeed what you're trying to do), the other way round:
或者(如果这确实是您想要做的),反过来:
#include <stdio.h>
#include <inttypes.h>
sscanf( str, "%" SCNx64, &uint64 );
Note that you cannot enforce widths etc. with the scanf()function family. It parses what it gets, which can yield undesired results when the input does not adhere to expected formatting. Oh, and the scanf()function family only knows (lowercase) "x", not (uppercase) "X".
请注意,您不能使用scanf()函数系列强制执行宽度等。它解析它得到的东西,当输入不符合预期的格式时,这可能会产生不需要的结果。哦,scanf()函数族只知道(小写)“x”,而不知道(大写)“X”。

