Re: sscanf and 0x80000000
Christopher Pisz <nospam@notanaddress.com> writes:
On 11/3/2014 1:46 PM, Scott Lurndal wrote:
Christopher Pisz <nospam@notanaddress.com> writes:
On 10/31/2014 11:38 PM, Ian Collins wrote:
Andrew Cooper wrote:
On 31/10/2014 21:43, Marcel Mueller wrote:
I recently had a problem with a GPU assembler. The program is mainly
C++11, but the parsing of expression components is done with sscanf.
This causes problems because sscanf cannot read the integer constant
"0x80000000". %i returns 0x7fffffff and %u cannot read hex numbers. I
could bet that this has been working with %i for many years.
I just tested with gcc 4.8.2 for OS/2 - works with %i.
But with gcc 4.8.2 Linux (Mint 17) the result is the bitwise not.
You are presumably on a 32bit system? The unsigned value 0x80000000 is
out of range for a 32bit signed integer.
As it would be on a 64 bit system where the code was compiler for 64 bit.
strtoull() is your friend.
It is.
It isn't my friend, because over and over I get to debug this problem
that a C-style programmer put into my code:
// Deprecated C headers
#include <stdio.h>
#include <stdlib.h>
// Standard Includes
#include <iostream>
int main()
{
std::string validzero("0");
std::string garbage("garbage");
std::cout << strtoul(validzero.c_str(), nullptr, 0) << std::endl;
std::cout << strtoul(garbage.c_str(), nullptr, 0) << std::endl;
The programmer is abusing strtoul in this case, of course. Probably
because some C++ ideologue has forced them to use the stupid output
stream crap.
A bad programmer can write bad code in any language.
Ok, show me an example in any form at all, C or otherwise, where we can
determine the difference between a valid value of zero and an error
please, for my own education is solving this bug that occurs countless
times.
I posted such an example earlier in the thread. Here's a more
complicated use of strtoull.
a_memory_per_socket[msocket] = strtoull(arg, &cp, 0);
if ((*cp == 'G') || (*cp == 'g')) {
cp++;
a_memory_per_socket[msocket] <<= 30;
} else if ((*cp == 'M') || (*cp == 'm')) {
cp++;
a_memory_per_socket[msocket] <<= 20;
} else if ((*cp == 'K') || (*cp == 'k')) {
cp++;
a_memory_per_socket[msocket] <<= 10;
}
if (*cp == ',') {
arg = cp + 1;
msocket++;
if (msocket > a_socket_count) {
lp->log("There are only %u sockets available\n",
a_socket_count);
return false;
}
continue;
}
// Round down to modulo 64k
a_memory_per_socket[msocket] &= ~0xffffull;
if ((cp == arg)
|| (*cp != '\0')) {
lp->log("Invalid memory size '%s' on socket %zu\n", arg, msocket);
return false;
}
Authoritative documentation for strtoul (man page, if you like) is here:
http://pubs.opengroup.org/onlinepubs/009695399/functions/strtoul.html