我在这里面临的主要问题是strtoll()在VC 2010(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
    .......
}

最佳答案

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

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

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


退货

strtolstrtollstrtoulstrtoull函数返回转换后的
值(如果有)。如果无法执行转换,则返回零。如果正确的值
超出可代表值的范围,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限制。

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

关于c - 错误C3861:“strtoll”:找不到标识符,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8239013/

10-12 16:11