user519569
user519569

Reputation: 83

strtoull with base 36 overflowing unsigned long long on Linux 32bit

Anyone know why using strtoull will overlow an unsigned long long? The value of "x" is 12 when I make the call, so I'm trying to convert a 12 digit base 36 num to unsigned long long.

This should work right? It doesn't matter whether I compile 32 or 64bit. I'm using g++ on redhat.

buffer is a char*

char *strPtr = buffer + ORDERIDOFFSET;
char *endPtr = strPtr + ORDERIDLENGTH;
long x = long((endPtr)) - long(buffer + ORDERIDOFFSET);
unsigned long long orderid = strtoull((buffer + ORDERIDOFFSET), &(endPtr), 36);

Thanks!

Upvotes: 0

Views: 325

Answers (2)

Zac Howland
Zac Howland

Reputation: 15870

You appear to be trying to use endPtr as an input parameter. std::strtoull takes the second parameter as an output parameter.

You may find it more robust to use std::stoull instead of std::strtoull:

char *strPtr = buffer + ORDERIDOFFSET;
char *endPtr = strPtr + ORDERIDLENGTH; // assuming ORDERIDLENGTH takes you 1 passed the end of the actual ID string
std::string s(strPtr, endPtr);
unsigned long long orderid = std::stoull(s, nullptr, 36);

Additionally,

long x = long((endPtr)) - long(buffer + ORDERIDOFFSET);

is not portable to 64-bit systems (you would truncate the address). I'm pretty sure you want

std::size_t x = endPtr - strPtr;

Upvotes: 1

rici
rici

Reputation: 241861

You seem to be under the misapprehension that endptr is an input parameter to strtoull, which tells it how long the input string is. It is not. It is an output parameter, which strtoull uses to tell you the first character it could not convert.

I presume that your buffer is not nul-terminated; probably there is an alphanumeric character following your 12-digit base-36 number.

By the way, imho, x would be better computed as endPtr - strPtr. Casting to long is not really correct.

Upvotes: 4

Related Questions