C 使用无符号int而不是无符号short会改变行为

C 使用无符号int而不是无符号short会改变行为,c,unsigned,short,integer-promotion,C,Unsigned,Short,Integer Promotion,我正在尝试K&R(练习2-3,第43页)用C语言编写的htoi(char*)函数 该函数用于将十六进制字符串转换为10进制 我相信我已经成功了。这是我的代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> enum {hexbase = 16}; typedef enum{false, true} bool; unsigned int h

我正在尝试K&R(练习2-3,第43页)用C语言编写的
htoi(char*)
函数

该函数用于将十六进制字符串转换为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;
}
当我删除
short
以使
firstIndex
成为
无符号int
而不是
无符号short int
时,我得到一个无限循环

因此,当我在
htoi(char*s)
中从
s
的后面开始时,
I>=firstIndex
永远不会计算为false


为什么会发生这种情况?我是否遗漏了一些琐碎的东西,或者我做了一些非常错误的事情导致了这种未定义的行为?

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

您可以更改:

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


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

哪个版本的K&R?第一版?这是第二版。即使程序调用了未定义的行为,问题的标题也会很糟糕。“Undefined behavior”在C中有一个特定的含义,它不适合仅仅因为程序不执行您想要的操作而使用。@PascalCuoq修复了…好奇:为什么在
unsigned int len=(unsigned int)(strlen(s))中使用type
unsigned int
strlen()
返回type
size\u t
时,我更愿意为(unsigned I=len-1;I>=firstIndex;I--)GRC这样做,因为它不会像您在同一问题中遇到的那样工作。以
0
firstIndex
值为例,那么
i>=firstIndex
将始终为真。另一种可能的结构是
for(unsigned i=len;i--;)
unsigned short
升级为signed
int
多年来造成了很多麻烦,在某些方面,它已经被证明是最糟糕的设计决策之一。(当然,他们不可能预见到所有的后果。)@ouah你是对的:)我会使用下面的I=len-1;i>=firstIndex | i>~0--(一)
for(int i = len-1; i >= firstIndex; i--)
for(int i = len-1; i >= (int) firstIndex; i--)