错误 C3861:“strtoll”:未找到标识符

Posted

技术标签:

【中文标题】错误 C3861:“strtoll”:未找到标识符【英文标题】:error C3861: 'strtoll': identifier not found 【发布时间】:2011-11-23 08:18:46 【问题描述】:

我在这里面临的主要问题是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 
    .......

【问题讨论】:

你在你的程序中有#include &lt;stdlib.h&gt;吗?既然long longunsigned long 长得多,为什么要尝试使用long long 变体? long long 是最新的 ISO 9899:99 C 标准“C99”的一部分,Microsoft 不支持该标准。 Visual Studio 仅支持从 1990 年开始已有 21 年历史的 C 标准。 【参考方案1】:

由于您的 return_valunsigned int,您可能应该使用自 C89 以来一直是标准的 strtoul(),因此受 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;

请注意,这比有符号整数转换的测试要简单,因为它必须考虑负 &lt;type&gt;_MIN 限制和 &lt;type&gt;_MAX 限制。

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

【讨论】:

另外,您还应该检查 retval &gt; UINT_MAX(在向下转换为 unsigned int 之前),以防它位于 64 位长平台上。 @bdonlan:是的 - 感谢(感谢两个 cmets)。我在没有看到您的评论的情况下修复了最后一段的失望(但答案的第一版没有包含这一点,并且您的评论是正确的)。我错过了我的 '=' 而不是 '==' 错字(但如果我编译了代码,编译器会警告我)。 你已经修复了向下转换,但留在了 ul > UINT_MAX 测试中,它现在总是错误的。 @DavidConrad:为什么你认为测试总是错误的?在 64 位 (Unix) 机器上,unsigned long 值远大于 unsigned int 的值是微不足道的。在 Windows 64 或 32 位系统上,您是正确的;然而,我相信代码也能在这些上正常工作——尽管编译器可能会决定对测试发出警告。如果这是一个问题,我会安排条件编译,可能会寻找ULONG_MAX != UINT_MAX,并且只有在两者不同时才进行比较。 哎呀!抱歉,我想的是 ULONG_MAX,而不是 UINT_MAX。我的错。【参考方案2】:

在 Visual Studio 中,请改用 _strtoi64() 方法。参数与strtoll相同。

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

#if defined(_MSC_VER)
#define strtoll _strtoi64
#endif

【讨论】:

@PaulR 是的,他特别说 VS。如果他希望它是可移植的,他应该使用定义将 _strtoi64 重新定义为 microsoft c 编译器上的 strtoll。 @bdonlan 是的,后来我注意到了,因为我在将一些代码移植到 VS C 编译器时遇到了问题,然后我有点忽略了他在做什么,只是告诉他为什么 strtoll 不起作用。 @JesusRamos,看看我对 wallyk 帖子的评论——实际上是有原因的【参考方案3】:

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

【讨论】:

是的,他使用 walk for long long int,但转换为 unsigned int...我有点跳过了,呵呵。 如果longint 大小相同,这是解析INT_MAX+1..UINT_MAX 之间值的合理方法。 @bdonlan:假设longint 大小相同是短视的。编写它非常简单易移植:应该强调的是,不要走环境敏感的懒惰捷径,因为它最终会中断时很容易花费大量时间。 我已经用 strol() 试过了,它可以工作,但我不确定它是否可以做和 walk() 一样的事情 @wallyk,实际上并不那么容易 - 直接使用它会为大于 LONG_MAX 的值给出错误答案(钳制到 LONG_MAX;参见 codepad.org/nu9L2AED);所有这些代码都假定long long 大于int;它没有假设long == int.【参考方案4】:

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

【讨论】:

以上是关于错误 C3861:“strtoll”:未找到标识符的主要内容,如果未能解决你的问题,请参考以下文章

错误 C3861:“_beginthreadex”:未找到标识符

C++ Visual Studio 2012 错误 C3861:'_T':找不到标识符?

VC ++ WINAPI窗体:找不到标识符(C3861错误)

错误 C3861:“execute_assert”:找不到标识符

error C3861: “getpid”: 找不到标识符

错误 C2039:“查找”:不是“标准”的成员