2

我在这里面临的主要问题是在 VC 2010 ( )中strtoll()被标记为错误。error C3861: 'strtoll': identifier not found如果我用 替换它会做同样的事情strtol()吗?

unsigned int get_uintval_from_arg(int argc, int index, char **argv,
                                  unsigned int lower_bound, unsigned int upper_bound) 
{  
    unsigned int return_val=0;

    if (index + 1 <= argc - 1)
    {
        return_val=(unsigned int)strtoll(argv[index+1],NULL,10);
        if (errno == EINVAL || errno== ERANGE) 
        {
            fprintf(stderr, "Could not parse argument %s for switch %s!\n",
                    argv[index], argv[index+1]);
            return 0;
        }
    }
    // ....... I will post the remaining part of the code if necessary 
    .......
}
4

4 回答 4

5

由于您return_valunsigned int,您可能应该使用strtoul()自 C89 以来一直是标准的,因此受 MSVC 支持(而strtoll()自 C99 以来仅是标准,不受 MSVC 支持)。

您对错误条件的测试不充分。errno调用转换函数前需要设置为零;您还需要检测是否报告了错误,这比看起来更棘手。

C99 标准的第 7.20.1.4 节“strtol、strtoll、strtoul 和 strtoull 函数”说:

退货

strtolstrtoll和函数返回转换strtoulstrtoull的值(如果有)。如果无法执行转换,则返回零。如果正确值超出可表示值的范围,则返回 LONG_MIN、LONG_MAX、LLONG_MIN、LLONG_MAX、ULONG_MAX 或 ULLONG_MAX(根据值的返回类型和符号,如果有),宏 ERANGE 的值为存储在errno.

您还必须查看存储在endptr转换函数参数中的值,以判断没有执行转换(与转换有效的零相反)。

如果主题序列为空或没有预期的形式,则不进行转换;的值nptr存储在 指向的对象中endptr,前提endptr是该对象不是空指针。

因此,您必须编写更像这样的代码(省略对 EINVAL 的测试,因为标准没有提到将这些函数设置errno为 EINVAL):

unsigned int return_val=0;

if (index + 1 <= argc - 1)
{
    char *end;
    unsigned long ul;
    errno = 0;
    ul = strtoul(argv[index+1], &end, 10);
    if ((ul == 0 && end == argv[index+1]) ||
        (ul == ULONG_MAX && errno == ERANGE) ||
        (ul > UINT_MAX))
    {
        fprintf(stderr, "Could not parse argument %s for switch %s!\n",
                argv[index], argv[index+1]);
        return 0;
    }
    retval = (unsigned int)ul;
}

请注意,这比有符号整数转换的测试要简单,后者必须考虑负<type>_MIN限制和<type>_MAX限制。

另请注意,您确实应该将结果记录在 an 中unsigned long,然后检查它是否符合您指定的范围,该范围可能限于 UINT_MAX(在类 Unix 64 位环境中可能小于 ULONG_MAX)。

于 2011-11-23T08:36:58.370 回答
2

在 Visual Studio 中使用_strtoi64()方法代替。它具有与 相同的参数strtoll

为了兼容性,您可以简单地使用定义将其包装为 strtoll (如果您需要可移植性),例如

#if defined(_MSC_VER)
#define strtoll _strtoi64
#endif
于 2011-11-23T08:20:19.327 回答
0

strtol()是 a 的正确库函数long。为了可移植性,声明return_val为 long or unsigned long。如果是后者,请查看 MSVC 是否提供strtoul().

于 2011-11-23T08:21:07.557 回答
0

出于您的目的,您应该使用strtoul,因为您正在转换为一种unsigned long类型,而不是一种signed long long类型(这是strtoll会做的)。如果需要在long longs 中读取,请使用 Microsoft 特定的_strtoi64;您可以在 Microsoft 平台上使用#defines 将其重命名为strtoll,或在特定于 Windows 的可移植性 shims 文件中编写包装函数(在私有标头中使用您自己的原型)。

于 2011-11-23T08:35:47.637 回答