我正在执行两个涉及 atoi 的操作,我想知道如何使用无符号整数执行此操作,因为 atoi 似乎将它们转换为有符号整数,从而导致环绕整数溢出。我想使用 32 位无符号整数,但 atoi 有效地将我限制为 31 位无符号整数。
if (multiplication_is_safe(atoi(argv[1]),atoi(argv[3])))
{
printf("%s * %s = %u \n", argv[1], argv[3], atoi(argv[1]) * atoi(argv[3]));
return 0;
} else
strtoul()
代替。
更长的答案是,即使您需要的只是有符号的 32 位整数,或者对无符号的 31 位感到满意,
atoi()
函数也不适合您正在做的事情。
atoi()
函数将字符串转换为整数。一个普通的有符号整数。然而,atoi()
不做的是错误处理。 atoi()
的规范所说的是“如果无法表示该值,则行为未定义。”
strto*() 系列函数都清楚地指定了如何处理错误,因此在所有情况下都应该将
atoi()
替换为对 strtol()
的调用(将字符串转换为 long),在这种情况下,因为您想要处理无符号整数,您应该使用 strtoul()
(将字符串转换为无符号长整型)。
另请注意,如果您想处理更大的数字,可以使用
strtoll()
和 strtoull()
函数将字符串转换为 long long 或 unsigned long long。 (如果您只是想处理最大可能的整数值,而不关心中间的所有内容,则可以使用 strtoimax()
和 strtoumax()
,分别返回 intmax_t
或 uintmax_t
类型的值。)
POSIX 文档:
根据您的平台,strtoul可能是您想要的:
strtoul()函数将字符串的起始部分转换为nptr 根据给定基数转换为 unsigned long int 值,该值必须 介于 2 到 36 之间,或者是特殊值 0。
无符号整数的 atoi 等价物
...我如何用无符号整数做到这一点...
关键问题是如何检测超出目标范围 [0 ... INT_MAX]`的值。
考虑字符串可以转换为大于
UINT_MAX
或小于 0 的值的情况。
使用
strtoul()
是常见的第一步,但是,它会很乐意将负数 "-123"
转换为某个大的无符号值,而不会抱怨或设置 errno
。
如果
"-123"
是一个问题,请考虑:
相反,请根据需要使用
strtol()
,然后使用 strtoul()
。
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
// Return true when successful (and set *value).
// Else return false and set *value to some value.
bool string_to_unsigned(const char *s, unsigned *value) {
char *endptr;
errno = 0;
int base = 10;
long lvalue = strtol(s, &endptr, base);
if (s == endptr) {
// No conversion.
*value = 0;
return 0;
}
if (lvalue < 0) {
*value = 0;
errno = ERANGE; // String is negative.
return false;
}
if (errno == ERANGE || lvalue > UINT_MAX) {
// To large, let us try again via an unsigned conversion.
errno = 0;
unsigned long ulvalue = strtoul(s, &endptr, base);
if (errno == ERANGE || ulvalue > UINT_MAX) {
errno = ERANGE;
*value = UINT_MAX;
return false; // Value is too large,
}
*value = (unsigned) ulvalue;
} else {
*value = (unsigned) lvalue;
}
// Is trailing non-numeric text OK?
// Maybe allow trailing white-space
while (isspace(*(unsigned char *)endptr)) {
endptr ++;
}
if (*endptr) {
return false; /// Trailing junk
}
return true;
}