32bit 64bit - Strtol implementation different behaviour on 32 and 64 bit machine -
#include <ctype.h> #include <string.h> #include <stdio.h> #include <tgmath.h> #include <limits.h> #include <stdbool.h> #include <errno.h> #define negative -1 #define positive 1 #define octal 8 #define decimal 10 #define hexadecimal 16 #define base_min 2 #define base_max 36 long int strtol (const char * str, char ** endptr, int base) { if(base < 0 || base == 1 || base > base_max) { errno = einval; return 0l; } else { bool conversion = true; int = 0, sign = positive, save; while(isspace(*(str + i))) i++; if(*(str + i) == '\0') { conversion = false; save = i; } if(*(str + i) == '-') { sign = negative; i++; } else if(*(str + i) == '+') i++; if(base == 0) // find out base { if(*(str + i) == '0') { if(toupper(*(str + + 1)) == 'x') { base = hexadecimal; i++; } else base = octal; i++; } else base = decimal; } else if(base == octal) { if(*(str + i) == '0') i++; } else if(base == hexadecimal) { if(*(str + i) == '0') if(*(str + + 1) == 'x' || *(str + + 1) == 'x') += 2; } int start = i, end, exp, check = i; long int long_int, sum, multiplier; if(conversion) // find out correct part of string corresponding number { if(base < decimal) { while(*(str + i) >= '0' && *(str + i) < base + '0') // numbers 0 base - 1 i++; } else if(base == decimal) { while(*(str + i) >= '0' && *(str + i) <= '9') // numbers 0 9 i++; } else { while((*(str + i) >= '0' && *(str + i) <= '9') || (toupper(*(str + i)) >= 'a' && toupper(*(str + i)) < 'a' + base - 10)) i++;// numbers 0 9 , uper , lowercase letters a + base - 11 } } if(i == check && conversion) //no digits @ { conversion = false; save = i; } else if(endptr != null && conversion) // assign pointer *endptr = (char *) (str + i); if(conversion) { for(end = - 1, exp = 0, long_int = 0l; end >= start; end--, exp++) { multiplier = pow(base, exp); sum = 0l; if(*(str + end) >= '0' && *(str + end) <= '9') sum = (*(str + end) - '0') * multiplier; else if(*(str + end) >= 'a' && *(str + i) <= (base == base_max ? 'z' : 'f')) sum = (*(str + end) - 'a' + 10) * multiplier; else if(*(str + end) >= 'a' && *(str + i) <= (base == base_max ? 'z' : 'f')) sum = (*(str + end) - 'a' + 10) * multiplier; if(long_int <= long_min + sum) { errno = erange; return long_min; } if(long_int >= long_max - sum) { errno = erange; return long_max; } else long_int += sum; } return sign * long_int; } else { if(endptr != null) {// if base 16 check if string given not in form 0xincorrect string in way need return xincorrect part of string if(base == hexadecimal && save >= 2 && toupper(*(str + save - 1)) == 'x' && *(str + save - 2) == '0') *endptr = (char *) str + save - 1; else if(base == octal && save >= 1 && *(str + save - 1) == '0') *endptr = (char *) str + save;// if string of base 8 , in form 0incorrect string else //then return after 0 endptr string *endptr = (char *) str;//in other cases no conversion done return original pointer } return 0l; } } }
i've got problem writing implementation of strtol() function. thing compiled on 64 bit machine , output correct today checked on machine 32-bit , got wrong. 32-bit machine showed result example string "7fffffff" out of range when on 64-bits results strtol succeded same th standard function. checked errno value , 32-bit machine it's set erange shouldn't , it's not not on 64-bit. have program checks if implementation gives same output standard 1 different strings. spent few hours looking possible bug i'm out of ideas? tips?
Comments
Post a Comment