c++ - 为什么 strtoul 不能按预期工作?

标签 c++ c gcc

您好,我写了一个小测试程序来检查我编写的函数如何将字符串(十六进制数)转换为无符号整数,我发现代码的行为因我使用的编译器或系统而异。

我编译了下面的代码:
(1) ideone C++4.3.2 https://ideone.com/LlcNWw
(2) g++ 4.4.7 on a centos6 (64bits)
(3) ubuntu12(64 位)上的 g++ 4.6.3
(4) cygwin(32位)环境下的g++ 4.9.3

正如预期的那样 (1) 和 (4) 返回并且它是完全正确的结果,因为第一个值“0x210000000”对于 32 位值来说太大了....

Error while converting Id (0x210000000).
success

但是 (2) 和 (3) 返回

success
success

所以问题是为什么在不同平台上使用不同编译器构建的相同简单 C 代码会返回相同结果...以及为什么 'strtoul("0x210000000", ....)' 没有将 'errno' 设置为'ERANGE' 表示第 33 到 37 位超出范围。

平台上的更多跟踪 (3) 给出:

Id (0x210000000) as ul = 0x10000000  - str_end  - errno 0.
sucess
Id (0x10000000) as ul = 0x10000000  - str_end  - errno 0.
sucess




   /* strtoul example */
#include <stdio.h>      /* printf, NULL */
#include <stdlib.h>     /* strtoul */
#include <errno.h>

signed int GetIdentifier(const char* idString)
{
  char *str_end;
  int id = -1;
  errno = 0;
  id = strtoul(idString, &str_end, 16);
  if ( *str_end != '\0' || (errno == ERANGE))
  {
    printf("Error while converting Id (%s).\n", idString);
    return -1;
  }

  // Return error if converted Id is more than 29-bit
  if(id > 0x1FFFFFFF)
  {
    printf("Error: Id (%s) should fit on 29 bits (maximum value: 0x1FFFFFFF).\n", idString);
    return -1;
  }
  printf("sucess\n");
  return id;
}


int main ()
{
  GetIdentifier("0x210000000");
  GetIdentifier("0x10000000");

  return 0;
}

最佳答案

0x210000000 大于 32 位,在 32 位系统上 long 通常是 32 位,这意味着您不能使用 strtoul 正确转换字符串。您需要使用 strtoull 并使用 unsigned long long 保证至少为 64 位。

当然,long longstrtoull是在 C99 中引入的,因此您可能需要添加例如-std=c99(或使用更高版本的标准,如 C11)使其正确构建。


问题似乎是您假设long 总是 32 位,而实际上它被定义为至少 32 位。参见例如this reference用于标准整数类型的最小位大小。

在某些平台和编译器上,long 可以大于 32 位。 64 位硬件上的 Linux 是一个典型的此类平台,其中 long 更大,即 64 位,这当然足以容纳 0x210000000,这导致 strtoul 没有给出错误。

关于c++ - 为什么 strtoul 不能按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35744066/

相关文章:

c - 在 clone() 之后通过指针访问父级中的变量

Char 用 Scanf 存储整个字符串?

c - 代码 : Incorrect checksum for freed objects?

c++ - H.264 over RTP - 识别 SPS 和 PPS 帧

c++ - 访问多层结构导致错误

c - 程序在 2147483647 之后打印 -ve 个整数

c++ - 即使已安装 Azure 管道也不使用指定的编译器

c++ - 警告 : second/third operand of conditional has no effect [-Wunused-value]

c++ - 取消引用 null 并不总是 UB?

c++ - boost::asio 在从串行端口读取时阻塞 std::cout