3

K&R による C プログラミング言語の機能を試していhtoi(char*)ます (Excercise 2-3、43 ページ)。

この関数は、16 進文字列を基数 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ために削除すると、無限ループが発生します。firstIndexunsigned intunsigned short int

sそのため、 inの後ろから開始すると、htoi(char* s)i >= firstIndexfalse と評価されることはありません。

なぜこれが起こるのですか?ささいなことを見逃しているのでしょうか、それともこの未定義の動作を引き起こすために何かひどく間違ったことをしたのでしょうか?

4

1 に答える 1

4

firstIndexisの場合、通常の算術変換によりunsigned intin i >= firstIndextheniは に変換されます。unsigned intしたがって、iが負の場合、比較式では大きな整数になります。firstIndexunsigned short intの場合i >= firstIndexfirstIndexは に昇格されint、2 つの符号付き整数が比較されます。

あなたは変えられる:

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

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

どちらの場合でも同じ動作をするようにします。

于 2015-03-08T20:47:08.883 に答える