以下C代码有什么问题?

Joh*_*ohn 2 c visual-studio-2010 strtol

我在这里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 
    .......
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 5

因为你return_val是一个unsigned int,你可能应该使用strtoul()自C89以来一直是标准的,因此MSVC支持(而strtoll()自C99以来只有标准,MSVC不支持).

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

第§7.20.1.4节'C99标准的strtol,strtoll,strtoul和strtoull函数'表示:

返回

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

您还必须阅读存储在endptr转换函数的参数中的值,以告知未执行任何转换(与转换的有效零相反).

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

所以,你必须编写更像这样的代码(省略对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;
}
Run Code Online (Sandbox Code Playgroud)

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

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