错误 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 <stdlib.h>
吗?既然long long
比unsigned long
长得多,为什么要尝试使用long long
变体?
long long
是最新的 ISO 9899:99 C 标准“C99”的一部分,Microsoft 不支持该标准。 Visual Studio 仅支持从 1990 年开始已有 21 年历史的 C 标准。
【参考方案1】:
由于您的 return_val
是 unsigned int
,您可能应该使用自 C89 以来一直是标准的 strtoul()
,因此受 MSVC 支持(而 strtoll()
自 C99 以来才成为标准,不受MSVC)。
您对错误条件的测试不充分。调用转换函数前需要将errno
设置为零;您还需要检测是否报告了错误,这比看起来更棘手。
C99 标准的第 7.20.1.4 节“strtol、strtoll、strtoul 和 strtoull 函数”说:
退货
strtol
、strtoll
、strtoul
和strtoull
函数返回转换后的 价值,如果有的话。如果无法执行转换,则返回零。如果正确的值 超出可表示值的范围,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 )。
【讨论】:
另外,您还应该检查retval > 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...我有点跳过了,呵呵。 如果long
和int
大小相同,这是解析INT_MAX+1..UINT_MAX
之间值的合理方法。
@bdonlan:假设long
和int
大小相同是短视的。编写它非常简单易移植:应该强调的是,不要走环境敏感的懒惰捷径,因为它最终会中断时很容易花费大量时间。
我已经用 strol() 试过了,它可以工作,但我不确定它是否可以做和 walk() 一样的事情
@wallyk,实际上并不那么容易 - 直接使用它会为大于 LONG_MAX
的值给出错误答案(钳制到 LONG_MAX
;参见 codepad.org/nu9L2AED);所有这些代码都假定long long
大于int
;它没有假设long == int
.【参考方案4】:
出于您的目的,您应该使用strtoul,因为您要转换为unsigned long
类型,而不是signed long long
类型(strtoll
会这样做)。如果您需要阅读long long
s,请使用微软特定的_strtoi64;您可以在 Microsoft 平台上使用 #define
s 将其重命名为 strtoll
,或者在特定于 Windows 的可移植性 shims 文件中编写包装函数(在私有标头中使用您自己的原型)。
【讨论】:
以上是关于错误 C3861:“strtoll”:未找到标识符的主要内容,如果未能解决你的问题,请参考以下文章
错误 C3861:“_beginthreadex”:未找到标识符
C++ Visual Studio 2012 错误 C3861:'_T':找不到标识符?
VC ++ WINAPI窗体:找不到标识符(C3861错误)