【问题标题】:Using unsigned int instead of unsigned short changes behaviour使用 unsigned int 而不是 unsigned short 会改变行为
【发布时间】:2015-05-09 23:55:00
【问题描述】:

我正在尝试 K&R 的 The C Programming Language 中的 htoi(char*) 函数(练习 2-3,第 43 页)。

该函数用于将十六进制字符串转换为以 10 为底的字符串。

我相信我已经成功了。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

enum {hexbase = 16};
typedef enum{false, true} bool;

unsigned int htoi(char* s);
bool hasHexPrefix(char* s);

int main(int argc, char** argv) {   

    if(argc <= 1) {
        printf("Error: Not enough arguments.\n");
        return EXIT_FAILURE;
    }else {
        for(int i = 1; i < argc; i++) {
            unsigned int numericVal = htoi(argv[i]);
            printf("%s => %u\n",argv[i],numericVal);
        }
    }
}

unsigned int htoi(char* s) {
    unsigned int output = 0;
    unsigned int len = (unsigned int)(strlen(s));

    unsigned short int firstIndex = hasHexPrefix(s) ? 2 : 0;

    /* start from the end of the str (least significant digit) and move to front */
    for(int i = len-1; i >= firstIndex; i--) {
        int currentChar = s[i];
        unsigned int correspondingNumericVal = 0;
        if(currentChar >= '0' && currentChar <= '9') {
            correspondingNumericVal = currentChar - '0';
        }else if(currentChar >= 'a' && currentChar <= 'f') {
            correspondingNumericVal = (currentChar - 'a') + 10;
        }else if(currentChar >= 'A' && currentChar <= 'F') {
            correspondingNumericVal = (currentChar - 'A') + 10;
        }else {
            printf("Error. Invalid hex digit: %c.\n",currentChar);
        }
        /* 16^(digitNumber) */
        correspondingNumericVal *= pow(hexbase,(len-1)-i);
        output += correspondingNumericVal;
    }

    return output;
}

bool hasHexPrefix(char* s) {
    if(s[0] == '0')
        if(s[1] == 'x' || s[1] == 'X')
            return true;

    return false;
}

我的问题在于 htoi(char*) 函数中的以下行:

unsigned short int firstIndex = hasHexPrefix(s) ? 2 : 0;

当我删除short 以使firstIndex 变为unsigned int 而不是unsigned short int 时,我得到一个无限循环。

所以当我从 htoi(char* s) 中的 s 后面开始时,i &gt;= firstIndex 永远不会计算为假。

为什么会这样?我是否遗漏了一些微不足道的事情,或者我做错了什么导致这种未定义的行为?

【问题讨论】:

  • K&R 的哪个版本?第一个?
  • 这是第二版。
  • 即使程序调用了未定义的行为,问题的标题也会很糟糕。 “未定义的行为”在 C 中有特定的含义,不适合仅仅因为程序没有做你想做的事情。
  • @PascalCuoq 已修复...
  • 好奇:当strlen()返回类型size_t时,为什么在unsigned int len = (unsigned int)(strlen(s));中使用类型unsigned int

标签: c unsigned short integer-promotion


【解决方案1】:

firstIndexunsigned int 时,在i &gt;= firstIndex 中,由于通常的算术转换,i 被转换为unsigned int。因此,如果i 为负数,它将在比较表达式中成为一个大整数。当firstIndexi &gt;= firstIndex 中为unsigned short int 时,firstIndex 被提升为int 并比较两个有符号整数。

你可以改变:

for(int i = len-1; i >= firstIndex; i--)

for(int i = len-1; i >= (int) firstIndex; i--)

在两种情况下具有相同的行为。

【讨论】:

  • 我宁愿做 for(unsigned i = len-1; i >= firstIndex; i--)
  • @GRC 这不起作用,因为您将陷入 OP 遇到的同一问题。以firstIndex 的值为0 为例,那么i &gt;= firstIndex 将始终为真。
  • 另一个可能的结构是for (unsigned i = len; i--; )
  • unsigned charunsigned short 升级为已签名的 int 多年来造成了如此多的麻烦,在某些方面它已被证明是最糟糕的设计决策之一。 (当然他们不可能预见到所有的后果)。
  • @ouah 你是对的 :) 我会使用以下 i = len-1; i >= 第一个索引 ||我 > ~0; --i)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 2011-05-19
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多