【问题标题】:unsigned long and atoi in CC中的无符号长和atoi
【发布时间】:2017-03-24 21:03:15
【问题描述】:

代码:

char temp[] = "1010000001010011";
printf("%s\n", temp);
unsigned long num = atoi(temp);
printf("%lu\n", num);

输出:

1010000001010011
4081617243

为什么 num 不是 41043?

【问题讨论】:

  • atoi 用于十进制数而不是二进制数。使用strtol 表示二进制。
  • 为什么会这样?
  • atoi() 将其输入解释为 十进制 数字的字符串表示形式。如果您想转换以不同基数表示的数字(例如基数 2),请使用 strtol()
  • 另请注意,当解释为十进制数时,您的输入字符串很可能会超过系统的最大可表示 long 值。
  • "为什么 num 不是 41043?"什么是 41043,它与什么有什么关系?

标签: c long-integer unsigned number-systems


【解决方案1】:

atoi("1010000001010011"); 尝试将文本作为十进制 字符序列转换为int。如果int 足够宽,它将采用十进制值 1,010,000,001,010,011。毫不奇怪,该值超出了 OP 的 int 范围,因此结果是 未定义的行为 或 UB。

要将字符串转换为二进制字符,请使用strtol()strtoul()

char temp[] = "1010000001010011";
char *endptr;
int base = 2;
unsigned long ulnum = strtoul(temp, &endptr, base);
if (endptr == temp) puts("No conversion");
else printf("%lu\n", ulnum);  // 41043

【讨论】:

    【解决方案2】:

    atoi 返回一个 int 值。十进制数 1010000001010011 是十六进制 39696F348895B 不适合 32 位变量,并被截断为十六进制 F348895B,这是有符号十进制值 -213350053。然而,将该值分配给unsigned long 是未定义的行为,尽管编译器生成的代码确实分配了该位模式,因为unsigned long 恰好是4081617243

    非常感谢@AnT 和@chux

    【讨论】:

    • atoi 中的溢出导致未定义的行为,而不是截断。
    【解决方案3】:

    Beacouse atoi() 将字符串转换为整数,而不是从二进制转换。 例如代码

    char str[]="123";
    printf("%d",atoi(str));
    

    将 123 打印为整数

    【讨论】:

      猜你喜欢
      • 2015-01-31
      • 2020-02-23
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 2011-10-11
      • 1970-01-01
      • 2013-12-19
      • 1970-01-01
      相关资源
      最近更新 更多