Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sscanf and 0x80000000

271 views
Skip to first unread message

Marcel Mueller

unread,
Oct 31, 2014, 5:43:35 PM10/31/14
to
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.

#include <stdio.h>
int main()
{ int i;
sscanf("0x80000000", "%i", &i);
printf("%x", i);
return 0;
}

The goal is to read an unsigned number in all common formats (decimal,
binary, octal, hex) from a string. The string does not necessarily end
after the number. I did not find format specifier that does the job.


Marcel

Melzzzzz

unread,
Oct 31, 2014, 5:54:29 PM10/31/14
to
#include <stdio.h>

int main()
{ long long i;
sscanf("0x80000000","%lli",&i);
printf("%llx\n", i);
return 0;
}

Problem is that 32 bit int is not long enough, just use long long
and all set...

--
Manjaro all the way!
http://manjaro.org/

Christopher Pisz

unread,
Oct 31, 2014, 6:34:26 PM10/31/14
to
or use C++ and drop the C style

#include <iostream>

int main()
{
long long i = 0x80000000;
std::cout << std::hex << i << std::endl;

return 0;
}


or if you will need the string later


#include <iostream>
#include <sstream>

int main()
{
long long i = 0x80000000;
std::ostringstream os;

os << std::hex << i;
std::cout << os.str() << std::endl;

return 0;
}


or at least #include <cstdlib> which has been for quite a long time now...





Geoff

unread,
Oct 31, 2014, 6:48:32 PM10/31/14
to
To be equivalent to the C code it needs to be

std::cout << "0x" << std::hex << i << std::endl;

Rick C. Hodgin

unread,
Oct 31, 2014, 6:54:50 PM10/31/14
to
On Friday, October 31, 2014 5:43:35 PM UTC-4, Marcel Mueller wrote:
> The goal is to read an unsigned number in all common formats (decimal,
> binary, octal, hex) from a string. The string does not necessarily end
> after the number. I did not find format specifier that does the job.

If you cannot get one to work and need a custom one, I would be willing
to write one for you using only C.

Best regards,
Rick C. Hodgin

Christopher Pisz

unread,
Oct 31, 2014, 7:07:20 PM10/31/14
to
Looks like he might want to go the other way too. If that is the case
use istringstream and operator >>

Just Google c++ streams in general. Much prettier than scanf and printf.
I've found doing format specifiers inside of string literals is just
plain error prone.







Geoff

unread,
Oct 31, 2014, 7:55:09 PM10/31/14
to
I like Christopher's solution, stay with C++ instead of C but this
would appear to be a bug in gcc 4.8.2. on that version of Linux. The
question is, is it a problem in sscanf or in printf? Breakpoint at the
printf line and examine the value of i in the debugger, is it
-2147483648 or 2147483647? If the former, you have a bug in printf
that is supposed to be taking an /unsigned/ i and outputting the hex
string. If the latter, then sscanf is interpreting 0x8000000 as -1.

Andrew Cooper

unread,
Oct 31, 2014, 11:15:17 PM10/31/14
to
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.

>
> #include <stdio.h>
> int main()
> { int i;
> sscanf("0x80000000", "%i", &i);
> printf("%x", i);
> return 0;
> }
>
> The goal is to read an unsigned number in all common formats (decimal,
> binary, octal, hex) from a string. The string does not necessarily end
> after the number. I did not find format specifier that does the job.

strtoull() is your friend.

~Andrew

Geoff

unread,
Nov 1, 2014, 12:23:04 AM11/1/14
to
On Sat, 01 Nov 2014 03:02:52 +0000, Andrew Cooper <am...@cam.ac.uk>
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.
>

Then why does it work on gcc 4.8.2 for OS/2 and not on Linux?
Why does it work on Visual Studio 2010 and LLVM on OSX 10.10?

Ian Collins

unread,
Nov 1, 2014, 12:39:04 AM11/1/14
to
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.

--
Ian Collins

Ian Collins

unread,
Nov 1, 2014, 12:45:22 AM11/1/14
to
Oops, not enough 0s to be out of range, I should learn to count.

--
Ian Collins

Jorgen Grahn

unread,
Nov 1, 2014, 12:55:54 AM11/1/14
to
On Fri, 2014-10-31, Christopher Pisz wrote:
> On 10/31/2014 5:48 PM, Geoff wrote:
>> On Fri, 31 Oct 2014 17:34:14 -0500, Christopher Pisz
>> <nos...@notanaddress.com> wrote:
>>
>>> On 10/31/2014 4:54 PM, Melzzzzz wrote:
>>>> On Fri, 31 Oct 2014 22:43:23 +0100
>>>> Marcel Mueller <news.5...@spamgourmet.org> 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.
>>>>>
>>>>> #include <stdio.h>
>>>>> int main()
>>>>> { int i;
>>>>> sscanf("0x80000000", "%i", &i);
>>>>> printf("%x", i);
>>>>> return 0;
>>>>> }
>>>>>
>>>>> The goal is to read an unsigned number in all common formats
>>>>> (decimal, binary, octal, hex) from a string. The string does not
>>>>> necessarily end after the number. I did not find format specifier
>>>>> that does the job.

...

> If that is the case use istringstream and operator >>
>
> Just Google c++ streams in general. Much prettier than scanf and printf.

I would have used strtoul() and friends instead -- I don't like
sscanf(), and I don't like operator >>.

> I've found doing format specifiers inside of string literals is just
> plain error prone.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Marcel Mueller

unread,
Nov 1, 2014, 3:15:55 AM11/1/14
to
On 31.10.14 23.48, Geoff wrote:
> To be equivalent to the C code it needs to be
>
> std::cout<< "0x"<< std::hex<< i<< std::endl;

This is by far not equivalent. Note that the requirement is to read an
unsigned number in all common formats (decimal, binary, octal, hex).
Using iostream is on of the last things I would do to parse strings.
First I would need to copy each string into a stringstream because the
tokenizer returns slices with start/length rather than individual
strings. Secondly I need to discover the number basis on my own.

With sscanf there is a quite simple pattern:
unsigned u;
int tmp_len;
if (sscanf(line + start, "%i%n", &u, &tmp_len) != 1 && tmp_len != len)
throw some error;
// got it

line points to the start of current line, start and len denote a slice
in line.

Then I can also write my own parser as Rick suggested. Only for the
conversion of digits and the multiplication with the number basis I do
not introduce stringstream.


Marcel

Marcel Mueller

unread,
Nov 1, 2014, 3:23:50 AM11/1/14
to
On 01.11.14 05.55, Jorgen Grahn wrote:
> I would have used strtoul() and friends instead

Interesting hint.

Any Ideas how to check for parser errors with strtoul? AFAIK it simply
stops reading on unparsable input and returns 0 in doubt.
Basically I need to check whether strtoul has read exactly all
characters in the part of the string that is to be converted.


Marcel

Rick C. Hodgin

unread,
Nov 1, 2014, 4:45:00 AM11/1/14
to
Is there some reason you don't want to write your own? You would
then have total control over the conversion, able to report in
whatever manner you require.

Alain Ketterlin

unread,
Nov 1, 2014, 4:58:05 AM11/1/14
to
Marcel Mueller <news.5...@spamgourmet.org> writes:

> On 01.11.14 05.55, Jorgen Grahn wrote:
>> I would have used strtoul() and friends instead
>
> Interesting hint.
>
> Any Ideas how to check for parser errors with strtoul? AFAIK it simply
> stops reading on unparsable input and returns 0 in doubt.

and stores a pointer to the first invalid character. See the manual:

| unsigned long int strtoul(const char *nptr, char **endptr, int base);
| [...]
| If endptr is not NULL, strtoul() stores the address of the first
| invalid character in *endptr. If there were no digits at all, str‐
| toul() stores the original value of nptr in *endptr (and returns 0).
| In particular, if *nptr is not '\0' but **endptr is '\0' on return, the
| entire string is valid.

-- Alain.

Marcel Mueller

unread,
Nov 1, 2014, 5:15:50 AM11/1/14
to
On 01.11.14 09.57, Alain Ketterlin wrote:
>> Any Ideas how to check for parser errors with strtoul? AFAIK it simply
>> stops reading on unparsable input and returns 0 in doubt.
>
> and stores a pointer to the first invalid character. See the manual:

Opps, sorry, for some reason I confusion strtoul with atoul.
But the problem with the number basis still exists.


Marcel

Alain Ketterlin

unread,
Nov 1, 2014, 5:52:56 AM11/1/14
to
What problem? From the man:

| The strtoul() function converts the initial part of the string in nptr
| to an unsigned long int value according to the given base, which must
| be between 2 and 36 inclusive, or be the special value 0.
|
| The string may begin with an arbitrary amount of white space (as deter‐
| mined by isspace(3)) followed by a single optional '+' or '-' sign. If
| base is zero or 16, the string may then include a "0x" prefix, and the
| number will be read in base 16; otherwise, a zero base is taken as 10
| (decimal) unless the next character is '0', in which case it is taken
| as 8 (octal).

-- Alain.

Marcel Mueller

unread,
Nov 1, 2014, 6:14:26 AM11/1/14
to
On 01.11.14 09.44, Rick C. Hodgin wrote:
> Is there some reason you don't want to write your own?

Reinvention of the wheel?
I simply could not believe that such simple task is not part of the
standard library.

> You would
> then have total control over the conversion, able to report in
> whatever manner you require.

In fact I ended up with the following code returning the number of
parsed characters:

size_t Parser::parseUInt(const char* src, uint32_t& dst)
{ dst = 0;
const char* cp = src;
uint32_t basis = 10;
uint32_t limit = UINT32_MAX / 10;
for (char c; (c = *cp) != 0; ++cp)
{ uint32_t digit = c - '0';
if (digit >= 10)
{ digit = toupper(c) - 'A';
if (digit < 6)
digit += 10;
else
{ if (dst == 0 && cp - src == 1)
switch (c)
{ case 'b': basis = 2; limit = UINT32_MAX/2; continue;
case 'o': basis = 8; limit = UINT32_MAX/8; continue;
case 'x': basis = 16; limit = UINT32_MAX/16; continue;
case 'd': continue;
}
break;
} }
if (dst > limit)
break;
dst *= basis;
if (dst > UINT32_MAX - digit)
break;
dst += digit;
}
return cp - src;
}

Maybe there are more elegant solutions, but at least it seems to work.


Marcel

Marcel Mueller

unread,
Nov 1, 2014, 6:19:44 AM11/1/14
to
On 01.11.14 10.52, Alain Ketterlin wrote:
>> But the problem with the number basis still exists.
>
> What problem? From the man:

The user of a compiler expects to be able to put constants in the for
1234 (decaimal), 0x1234 (hex) as well as octal and binary. If I want to
implement this I need to parse the string before strtoul. At that point
strtoul does no longer help very much. So I ended up with Rick's
suggestion: I wrote my own parser for uint32_t.


Marcel

Jorgen Grahn

unread,
Nov 1, 2014, 7:11:03 AM11/1/14
to
On Sat, 2014-11-01, Marcel Mueller wrote:
> On 01.11.14 05.55, Jorgen Grahn wrote:
>> I would have used strtoul() and friends instead
>
> Interesting hint.
>
> Any Ideas how to check for parser errors with strtoul?

Yes -- read the documentation. The man page on Linux is very clear on
the subject.

> AFAIK it simply
> stops reading on unparsable input and returns 0 in doubt.

You're probably thinking of atoi() or something.

Jorgen Grahn

unread,
Nov 1, 2014, 7:34:05 AM11/1/14
to
On Sat, 2014-11-01, Marcel Mueller wrote:
> On 01.11.14 10.52, Alain Ketterlin wrote:
>>> But the problem with the number basis still exists.
>>
>> What problem? From the man:
>
> The user of a compiler expects to be able to put constants in the for
> 1234 (decaimal), 0x1234 (hex) as well as octal and binary. If I want to
> implement this I need to parse the string before strtoul.

You dodge Alain's question, but you're really just saying strtoul()
doesn't have support for binary input, right? Decimal, octal and hex
are all there.

Alain Ketterlin

unread,
Nov 1, 2014, 8:19:07 AM11/1/14
to
Marcel Mueller <news.5...@spamgourmet.org> writes:

> In fact I ended up with the following code returning the number of
> parsed characters:
>
> size_t Parser::parseUInt(const char* src, uint32_t& dst)

[buggy code removed]

> Maybe there are more elegant solutions, but at least it seems to work.

Have you tried with "0f"? It fails.

If you need binary, it is trivial to wrap strtoul to check for leading
"0b" (after optional spaces if you need that). I leave it to you do
decide whether it is elegant. At least, it will work.

-- Alain.

Ben Bacarisse

unread,
Nov 1, 2014, 8:35:19 AM11/1/14
to
When the behaviour is undefined, pretty much anything can happen. If
the string scanned represents a value that is out of range for the
target type, the behaviour is undefined. (The code then passes an int
where printf expects an unsigned int. This, again, is technically
undefined, though I image the number of implementations that do anything
but the obvious thing is zero.)

Many people think of hex numbers as representing bit patterns, but in
this context, 0x80000000 just means 2147483648 and that can't be
represented in the target type. Storing the maximum positive value
seems like a reasonable choice for an implementation, but it is
permitted to store whatever it likes.

In practice, this behaviour is a property by the library your code is
linked with, and the library version is often only very loosely tied to
the compiler version. That's the general explanation for why the same
compiler produces different result on different systems.

--
Ben.

Scott Lurndal

unread,
Nov 3, 2014, 10:14:22 AM11/3/14
to
Marcel Mueller <news.5...@spamgourmet.org> writes:
>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.
>
>#include <stdio.h>
>int main()
>{ int i;
> sscanf("0x80000000", "%i", &i);

i = strtoull("0x80000000", NULL, 0);

handles base 8, 10 and 16 (based on standard prefix interpretation
of leading 0 or 0x for octal/hex respectively). More powerful yet
if you use the middle parameter as well:

for example:

char *cp;

g_dist_bar = strtoull(argv[arg], &cp, 0);
if ((cp == argv[arg]) // Not numeric?
|| (*cp != '\0') // or trailing garbage?
|| (g_dist_bar == 0) // or value == 0
|| (g_dist_bar & 0xfff)) { // or value not congruent to zero modulo 4096.
lp->log("Illegal Distributor Base Address '%s'\n", argv[arg]);
return false;
}
arg++;

scott

Christopher Pisz

unread,
Nov 3, 2014, 10:43:46 AM11/3/14
to
On 11/1/2014 2:15 AM, Marcel Mueller wrote:
> On 31.10.14 23.48, Geoff wrote:
>> To be equivalent to the C code it needs to be
>>
>> std::cout<< "0x"<< std::hex<< i<< std::endl;
>
> This is by far not equivalent. Note that the requirement is to read an
> unsigned number in all common formats (decimal, binary, octal, hex).

and streams don't do that?
std::oct
std::hex
std::dec

> Using iostream is on of the last things I would do to parse strings.

Why? Do you like to reinvent the wheel?

> First I would need to copy each string into a stringstream because the
> tokenizer returns slices with start/length rather than individual
> strings.

You don't know how to specify a delimiter or a range?


> Secondly I need to discover the number basis on my own.

One would assume you know the number basis or nothing you try is going
to work.

> With sscanf there is a quite simple pattern:
> unsigned u;
> int tmp_len;
> if (sscanf(line + start, "%i%n", &u, &tmp_len) != 1 && tmp_len != len)
> throw some error;
> // got it
>
> line points to the start of current line, start and len denote a slice
> in line.

Looks like you knew the number basis there ^

> Then I can also write my own parser as Rick suggested.

If you do that, I hope no one employs you.
There are is enough code out there already where people think they could
do better than the standard library and failed.

Christopher Pisz

unread,
Nov 3, 2014, 2:17:56 PM11/3/14
to
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;

// Done
return 0;
}


Such problems don't exist using sstream for conversion, because it has a
way to indicate failure that differs from a valid conversion.

Scott Lurndal

unread,
Nov 3, 2014, 2:47:01 PM11/3/14
to
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.

Ian Collins

unread,
Nov 3, 2014, 3:17:42 PM11/3/14
to
Christopher Pisz wrote:
> On 10/31/2014 11:38 PM, Ian Collins wrote:
>> Andrew Cooper wrote:
>>
>>> 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>

Deprecated by whom?

> // Standard Includes
> #include <iostream>
>
>
> int main()
> {
> std::string validzero("0");
> std::string garbage("garbage");
>
> std::cout << strtoul(validzero.c_str(), nullptr, 0) << std::endl;

So you have been seeing bugs in C++ 11 code over and over?

> Such problems don't exist using sstream for conversion, because it has a
> way to indicate failure that differs from a valid conversion.

As does strtoull(), read the man page.

--
Ian Collins

Christopher Pisz

unread,
Nov 3, 2014, 3:19:43 PM11/3/14
to
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 don't see how showing the result using cout has anything to do with
the problem.

use printf if you like, the result is the same.








Christopher Pisz

unread,
Nov 3, 2014, 3:24:47 PM11/3/14
to
On 11/3/2014 2:17 PM, Ian Collins wrote:
> Christopher Pisz wrote:
>> On 10/31/2014 11:38 PM, Ian Collins wrote:
>>> Andrew Cooper wrote:
SNIP
>> // Deprecated C headers
>> #include <stdio.h>
>> #include <stdlib.h>
>
> Deprecated by whom?

by <cstdlib>

>
>> // Standard Includes
>> #include <iostream>
>>
>>
>> int main()
>> {
>> std::string validzero("0");
>> std::string garbage("garbage");
>>
>> std::cout << strtoul(validzero.c_str(), nullptr, 0) <<
>> std::endl;
>
> So you have been seeing bugs in C++ 11 code over and over?
>
>> Such problems don't exist using sstream for conversion, because it has a
>> way to indicate failure that differs from a valid conversion.
>
> As does strtoull(), read the man page.

I don't have "man", because I am not on *nix.
I do have Google. Here is the same example using their reference, with
the same problem

// C headers
#include <stdio.h>
#include <stdlib.h>

// Standard Includes
#include <climits>
#include <iostream>


int main()
{
std::string zero("0");
std::string garbage("garbage");

unsigned long long validZeroConverted = strtoul(zero.c_str(),
nullptr, 0);
unsigned long long garbageConverted = strtoul(garbage.c_str(),
nullptr, 0);

if( validZeroConverted != ULONG_MAX )
{
std::cout << strtoul(zero.c_str(), nullptr, 0) << std::endl;
}
else
{
std::cout << "Could not convert zero" << std::endl;
}

if( garbageConverted != ULONG_MAX )
{
std::cout << strtoul(garbage.c_str(), nullptr, 0) << std::endl;
}
else
{
std::cout << "Could not convert garbage" << std::endl;
}

// Done
return 0;
}


Please show me Ian, how do we determine the difference between a valid
value of zero and an error Ian. Now for argument's sake, but because I
would simply like to know if it exists at all or if strtoxxx functions
simply cannot handle a value of zero.

The only way I can figure is to look at the string beforehand and
compare it to "0", which seems pretty darn silly.



Christopher Pisz

unread,
Nov 3, 2014, 3:27:23 PM11/3/14
to
Peanut butter on my fingers.

Please show me Ian, how do we determine the difference between a valid
value of zero and an error. Not for argument's sake, but because I
would simply like to know if it exists at all. Can strtoxxx functions
simply cannot handle a value of zero?

Paavo Helde

unread,
Nov 3, 2014, 3:37:50 PM11/3/14
to
Christopher Pisz <nos...@notanaddress.com> wrote in
news:m38o9r$sgn$1...@dont-email.me:

>
> Please show me Ian, how do we determine the difference between a valid
> value of zero and an error Ian. Now for argument's sake, but because I
> would simply like to know if it exists at all or if strtoxxx functions
> simply cannot handle a value of zero.
>
> The only way I can figure is to look at the string beforehand and
> compare it to "0", which seems pretty darn silly.

Here you go:

#include <string>
#include <iostream>
#include <string.h>

unsigned long my_strtoul(const std::string& s) {
char* errPtr;
unsigned long result = strtoul(s.c_str(), &errPtr, 0);
if (*errPtr) {
throw std::runtime_error("not a numeric string: \"" + s + "\"");
} else {
return result;
}
}

int main()
{
std::string zero("0");
std::string garbage("garbage");

unsigned long long validZeroConverted = my_strtoul(zero);

try {
std::cout << my_strtoul(zero) << std::endl;;
} catch(const std::exception& e) {
std::cout << "Could not convert zero: " << e.what() <<
std::endl;
}

try {
std::cout << my_strtoul(garbage) << std::endl;;
} catch(const std::exception& e) {
std::cout << "Could not convert garbage: " << e.what() <<
std::endl;
}

// Done
return EXIT_SUCCESS;
}



Output:

0
Could not convert garbage: not a numeric string: "garbage"

Ben Bacarisse

unread,
Nov 3, 2014, 3:48:10 PM11/3/14
to
Christopher Pisz <nos...@notanaddress.com> writes:
<snip>
> Please show me Ian, how do we determine the difference between a valid
> value of zero and an error. Not for argument's sake, but because I
> would simply like to know if it exists at all. Can strtoxxx functions
> simply cannot handle a value of zero?

When no conversion can be done, the strto* functions set the pointer
pointed to by they second argument (it is is not null) to the value of
the first. Thus, after

char *end_ptr;
unsigned long u = strtoul(str, &endptr, 0);

if endptr == str you know that no conversion was done, and the return
(which will be zero), is meaningless. Testing for out-of-range errors
is a bit more fiddly since it uses errno, but it does not complicate
this situation since zero is never returned in these cases.

> The only way I can figure is to look at the string beforehand and
> compare it to "0", which seems pretty darn silly.

No need.

--
Ben.

Melzzzzz

unread,
Nov 3, 2014, 3:57:30 PM11/3/14
to
On Mon, 03 Nov 2014 14:24:33 -0600
Christopher Pisz <nos...@notanaddress.com> wrote:

>
>
> Please show me Ian, how do we determine the difference between a
> valid value of zero and an error Ian.

Check errno... and reset errno to 0 before call.
There is errno.h in your implementation? It's C standard
header?



--
Manjaro all the way!
http://manjaro.org/

Christopher Pisz

unread,
Nov 3, 2014, 4:03:27 PM11/3/14
to
So, this is confusion from bad documentation

Because, my crappy source says,
"
Parameters
str
C-string beginning with the representation of an integral number.
endptr
Reference to an object of type char*, whose value is set by the function
to the next character in str after the numerical value.
This parameter can also be a null pointer, in which case it is not used.
base
Numerical base (radix) that determines the valid characters and their
interpretation.
If this is 0, the base used is determined by the format in the sequence
(see strtol for details).
"

Which makes no mention of the second param being used to indicate an
error condition.

So, I went and got hold of a man page:

"If endptr is not NULL, strtol() stores the address of the first invalid
character in *endptr. If there were no digits at all, however,
strtol()
stores the original value of str in *endptr. (Thus, if *str is
not `\0'
but **endptr is `\0' on return, the entire string was valid.)"


I still fail to see why anyone wants to use this rather than a stream or
a lexical_cast. It's so C90.

Is the preference due to performance, plain hatred of streams, or
something else?

In my tests, the performance really wasn't that much different. Of
course, one could argue whether or not my performance test is written
properly for such an exercise. But I doubt its going to make more than a
microsecond of difference.

I am really not exaggerating when I speak of debugging the
aforementioned scenario over and over again. Bad programmers or not,
they don't seem to make such a mistake when told to use a stream or
lexical cast instead. We're gonna have to work with bad programmers in
most cases.















Paavo Helde

unread,
Nov 3, 2014, 4:04:00 PM11/3/14
to
Paavo Helde <myfir...@osa.pri.ee> wrote in
news:XnsA3DAE62CE23ECm...@216.196.109.131:

> Christopher Pisz <nos...@notanaddress.com> wrote in
> news:m38o9r$sgn$1...@dont-email.me:
>
>>
>> Please show me Ian, how do we determine the difference between a
>> valid value of zero and an error Ian. Now for argument's sake, but
>> because I would simply like to know if it exists at all or if
>> strtoxxx functions simply cannot handle a value of zero.
>>
>> The only way I can figure is to look at the string beforehand and
>> compare it to "0", which seems pretty darn silly.
>
> Here you go:
>
> #include <string>
> #include <iostream>
> #include <string.h>
>
> unsigned long my_strtoul(const std::string& s) {
> char* errPtr;
> unsigned long result = strtoul(s.c_str(), &errPtr, 0);
> if (*errPtr) {
> throw std::runtime_error("not a numeric string: \"" + s +
> "\"");
> } else {
> return result;
> }
> }


Sorry, a bit more reliable version is:

unsigned long my_strtoul(const std::string& s) {
errno = 0;
char* errPtr;
unsigned long result = strtoul(s.c_str(), &errPtr, 0);
if (*errPtr || errPtr==s.c_str() || errno!=0) {

Scott Lurndal

unread,
Nov 3, 2014, 4:16:04 PM11/3/14
to
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

Paavo Helde

unread,
Nov 3, 2014, 4:18:17 PM11/3/14
to
Christopher Pisz <nos...@notanaddress.com> wrote in news:m38qic$6ed$1
@dont-email.me:
>
> So, this is confusion from bad documentation

I have found Linux man pages are often more easily readable than other
variants, and have grown a habit to google, e.g.: man strtoul linux

>
>
> I still fail to see why anyone wants to use this rather than a stream
or
> a lexical_cast. It's so C90.
>
> Is the preference due to performance, plain hatred of streams, or
> something else?

The former. Streams are invariably several times slower than other
options. For a simple string concatenation from pieces, appending to a
std::string with += operator is at least 2 times faster than using an
ostringstream.

Lexical_cast can be faster in principle (if not implemented via streams,
of course), and has the nice feature of throwing exceptions
automatically, which is not the case neither for C functions nor C++
streams. So in newer code and when the performance is not so important,
I'm using lexical_cast.


Cheers
Paavo

Ben Bacarisse

unread,
Nov 3, 2014, 4:19:57 PM11/3/14
to
Christopher Pisz <nos...@notanaddress.com> writes:

> On 11/3/2014 1:46 PM, Scott Lurndal wrote:
<snip>
>> The programmer is abusing strtoul in this case, of course.
<snip>
> 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 an explanation, but here's a code fragment that tests very
various conditions:

char *endp;
errno = 0;

unsigned long u = strtoul(str, &endp, 0);

if (endp == str) {
// No conversion was done.
// This happens on inputs like "", " ", "garbage" and "+";
}
else if (errno == ERANGE) {
// The string represents and value that is out of range for
// unsigned long. u will be == ULONG_MAX. If using strtol, u
// would be either LONG_MAX or LONG_MIN so you can tell which
// side of zero the value was out of range.
}
else if (endp[strspn(endp, " \t")] != 0) {
// You can also test that what is left after the number is as
// expected though exactly what will vary from situation to
// situation. It may be OK for anything at all to follow the
// number, or it might be required that there be nothing at all
// (*endptr == 0). This example tests for anything other than
// trailing spaces and tabs.
}
else {
// All good. u really does represent a value that can be stored
// in an unsigned long. If u == ULONG_MAX or u == 0 that's
// because the input really did represent ULONG_MAX or zero.
}

There are still issues with these functions. For example, the unsigned
versions must accept signed numbers and convert them. That's not what
everyone wants, of course, but that's how they are specified.

<snip>
--
Ben.

Christopher Pisz

unread,
Nov 3, 2014, 4:22:39 PM11/3/14
to
Learn something new every day. Thanks guys.

Ian Collins

unread,
Nov 3, 2014, 4:33:24 PM11/3/14
to
Christopher Pisz wrote:
> On 11/3/2014 2:17 PM, Ian Collins wrote:
>> Christopher Pisz wrote:
>>> On 10/31/2014 11:38 PM, Ian Collins wrote:
>>>> Andrew Cooper wrote:
> SNIP
>>> // Deprecated C headers
>>> #include <stdio.h>
>>> #include <stdlib.h>
>>
>> Deprecated by whom?
>
> by <cstdlib>

A header can only be deprecated by the standard, not by another header.

The general consensus on projects I've working on is the <cxxx> headers
are a wast of time: if you are using the C standard library functions,
don't try and hide them.

--
Ian Collins

Ben Bacarisse

unread,
Nov 3, 2014, 5:29:36 PM11/3/14
to
Melzzzzz <m...@zzzzz.com> writes:

> On Mon, 03 Nov 2014 14:24:33 -0600
> Christopher Pisz <nos...@notanaddress.com> wrote:
>
>> Please show me Ian, how do we determine the difference between a
>> valid value of zero and an error Ian.
>
> Check errno... and reset errno to 0 before call.

strtoul does not set errno when zero is returned, so you can't use it to
find out anything about a zero return. It can be used, however, to
detect out of range inputs.

<snip>
--
Ben.

Andrew Cooper

unread,
Nov 3, 2014, 6:45:12 PM11/3/14
to
errno = 0;
val = strtoul(some_str, NULL, 0);
if ( errno )
// Some error. val undefined
else
// val is good, even if 0.

~Andrew

Ben Bacarisse

unread,
Nov 3, 2014, 7:14:22 PM11/3/14
to
Andrew Cooper <am...@cam.ac.uk> writes:

> On 03/11/2014 20:19, Christopher Pisz wrote:
<snip>
>> 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.
>
> errno = 0;
> val = strtoul(some_str, NULL, 0);
> if ( errno )
> // Some error. val undefined
> else
> // val is good, even if 0.

No, that's wrong in a couple of ways. When no conversion can be done,
zero is returned and errno is not set, and when errno is set val is not
undefined -- it must be ULONG_MAX.

--
Ben.

Andrew Cooper

unread,
Nov 3, 2014, 8:15:13 PM11/3/14
to
Fine - sticking strictly to C and not relying on POSIX (not that there
is any reasonable excuse for avoiding POSIX if it is available):

errno = 0;
val = strtoul(some_str, &endptr, 0);
if ( errno || (endptr == some_str) )
// Some error. val as about as useful as being undefined.
else
// val is good, even if 0.

~Andrew

Ben Bacarisse

unread,
Nov 3, 2014, 8:32:58 PM11/3/14
to
Andrew Cooper <am...@cam.ac.uk> writes:

> On 04/11/2014 00:14, Ben Bacarisse wrote:
>> Andrew Cooper <am...@cam.ac.uk> writes:
>>
>>> On 03/11/2014 20:19, Christopher Pisz wrote:
>> <snip>
>>>> 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.
>>>
>>> errno = 0;
>>> val = strtoul(some_str, NULL, 0);
>>> if ( errno )
>>> // Some error. val undefined
>>> else
>>> // val is good, even if 0.
>>
>> No, that's wrong in a couple of ways. When no conversion can be done,
>> zero is returned and errno is not set, and when errno is set val is not
>> undefined -- it must be ULONG_MAX.
>>
>
> Fine - sticking strictly to C and not relying on POSIX (not that there
> is any reasonable excuse for avoiding POSIX if it is available):

I think POSIX only says that strtoul *may* fail with errno == EINVAL
when there is no conversion (the "false zero" return case), so I don't
think you can reply on that, even with the POSIX extensions.

<snip>
--
Ben.

Juha Nieminen

unread,
Nov 4, 2014, 2:56:52 AM11/4/14
to
Ian Collins <ian-...@hotmail.com> wrote:
> The general consensus on projects I've working on is the <cxxx> headers
> are a wast of time: if you are using the C standard library functions,
> don't try and hide them.

Personally, I prefer not to pollute the global namespace.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Jouko Koski

unread,
Nov 4, 2014, 3:16:38 AM11/4/14
to
"Juha Nieminen" wrote:
> Ian Collins <ian-...@hotmail.com> wrote:
>> The general consensus on projects I've working on is the <cxxx> headers
>> are a wast of time: if you are using the C standard library functions,
>> don't try and hide them.
>
> Personally, I prefer not to pollute the global namespace.

Well, the C standard library functions are in the global namespace already,
aren't they? C++ headers just draw them to the std namespace, too. Some C++
headers declare additional things like overloaded functions in the std
namespace. A bit of a mess! Has anybody seen a summary of how this is
supposed to work and how it really works?

--
Jouko

Martijn Lievaart

unread,
Nov 4, 2014, 3:20:11 AM11/4/14
to
On Tue, 04 Nov 2014 01:06:26 +0000, Andrew Cooper wrote:

> On 04/11/2014 00:14, Ben Bacarisse wrote:
>> Andrew Cooper <am...@cam.ac.uk> writes:
>>
>>> On 03/11/2014 20:19, Christopher Pisz wrote:
>> <snip>
>>>> 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.
>>>
>>> errno = 0;
>>> val = strtoul(some_str, NULL, 0);
>>> if ( errno )
>>> // Some error. val undefined
>>> else
>>> // val is good, even if 0.
>>
>> No, that's wrong in a couple of ways. When no conversion can be done,
>> zero is returned and errno is not set, and when errno is set val is not
>> undefined -- it must be ULONG_MAX.
>>
>>
> Fine - sticking strictly to C and not relying on POSIX (not that there
> is any reasonable excuse for avoiding POSIX if it is available):

Why rely on POSIX when it isn't needed? One could argue that one can use
strtoul the way you showed if Posix compliency is known, but this may
create a proting bug later on. Why risk it if the alternative is one
comparison extra?

>
> errno = 0;
> val = strtoul(some_str, &endptr, 0);
> if ( errno || (endptr == some_str) )
> // Some error. val as about as useful as being undefined.
> else
> // val is good, even if 0.

This thread is a good example why streams can be easier than the C
equivalents. Note I don't find streams easier to use when formatting
output over the C equivalents, but for input i do.

M4

Juha Nieminen

unread,
Nov 4, 2014, 7:38:11 AM11/4/14
to
Jouko Koski <joukokos...@netti.fi> wrote:
> Well, the C standard library functions are in the global namespace already,
> aren't they?

I don't think you can rely on that. IIRC the newest gcc does not bring
them to the global namespace if you use the <c...> versions.

peter koch

unread,
Nov 4, 2014, 8:11:32 AM11/4/14
to
Den tirsdag den 4. november 2014 08.56.52 UTC+1 skrev Juha Nieminen:
> Ian Collins <ian-...@hotmail.com> wrote:
> > The general consensus on projects I've working on is the <cxxx> headers
> > are a wast of time: if you are using the C standard library functions,
> > don't try and hide them.
>
> Personally, I prefer not to pollute the global namespace.

If I remember correctly, the <c....> equivalents may - and often do - pollute the global namespace as well. So using the <c....> includes only obscures the fact that the global namespace is/might be polluted for the user. This also risks making your code non-portable because using a global namespace function (e.g. printf) will not be detected by the compiler.

/Peter

Jouko Koski

unread,
Nov 4, 2014, 9:15:26 AM11/4/14
to
"Juha Nieminen" wrote:
> Jouko Koski <joukokos...@netti.fi> wrote:
>> Well, the C standard library functions are in the global namespace
>> already,
>> aren't they?
>
> I don't think you can rely on that.

Yes, it is not mandated by the standard, but it is allowed by the standard.
All real implementations I have seen implement the <cxxxxx> headers like
this:

#include <xxxxx.h>
namespace std {
using ::func;
}

That's why I asked if anybody has summarized how this is supposed to work
and how it really works. Are we any better off with <cxxxxx> headers than
without them? Ok, the overloaded functions have to go somewhere, but still?

I think a standard C library function - say, sscanf - could well have stayed
in the global namespace. If there were any ambiguity, one can easily resolve
it by writing ::sscanf vs. somethingelse::sscanf. Having std::sscanf does
not help much, unless one just likes have the std:: because it is used
elsewhere - like say, with std::string - too.

--
Jouko

Rosario193

unread,
Nov 4, 2014, 11:26:46 AM11/4/14
to
On Fri, 31 Oct 2014 22:43:23 +0100, Marcel Mueller
<news.5...@spamgourmet.org> 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.
>
>#include <stdio.h>
>int main()
>{ int i;
> sscanf("0x80000000", "%i", &i);
> printf("%x", i);
> return 0;
>}
>
>The goal is to read an unsigned number in all common formats (decimal,
>binary, octal, hex) from a string. The string does not necessarily end
>after the number. I did not find format specifier that does the job.

Borland compiler compile the progr that return print:
80000000
what about:

#include <stdio.h>

int main(void)
{ unsigned i;
sscanf("0x80000000", "%x", &i);
printf("%x", i);
return 0;
}




>
>Marcel

Öö Tiib

unread,
Nov 4, 2014, 12:59:44 PM11/4/14
to
Assembler text may contain decimal, octal and hexadecimal numeric
constants. OP wanted to handle all cases with single 'sscanf'.
He wanted input "042" resulting with 'i' being 34,
input "42" resulting with 'i' being 42
and input "0x42" resulting with 'i' being 66.

What answers gives your borland to those inputs?

Rosario193

unread,
Nov 4, 2014, 2:15:14 PM11/4/14
to
On Tue, 4 Nov 2014 09:59:31 -0800 (PST), 嘱 Tiib wrote:
>On Tuesday, 4 November 2014 18:26:46 UTC+2, Rosario193 wrote:
>> On Fri, 31 Oct 2014 22:43:23 +0100, Marcel Mueller wrote:

>> >#include <stdio.h>
>> >int main()
>> >{ int i;
>> > sscanf("0x80000000", "%i", &i);
>> > printf("%x", i);
>> > return 0;
>> >}
>> >
>> >The goal is to read an unsigned number in all common formats (decimal,
>> >binary, octal, hex) from a string. The string does not necessarily end
>> >after the number. I did not find format specifier that does the job.
>>
>> Borland compiler compile the progr that return print:
>> 80000000
>> what about:

>Assembler text may contain decimal, octal and hexadecimal numeric
>constants. OP wanted to handle all cases with single 'sscanf'.
>He wanted input "042" resulting with 'i' being 34,
>input "42" resulting with 'i' being 42
>and input "0x42" resulting with 'i' being 66.

yes i understand now... thank you
for that i would use strtoul()....

>What answers gives your borland to those inputs?

for the C op code above it print: "80000000"...

Jorgen Grahn

unread,
Nov 5, 2014, 2:05:39 AM11/5/14
to
On Mon, 2014-11-03, Paavo Helde wrote:
> Christopher Pisz <nos...@notanaddress.com> wrote in news:m38qic$6ed$1
> @dont-email.me:
>>
>> So, this is confusion from bad documentation
>
> I have found Linux man pages are often more easily readable than other
> variants, and have grown a habit to google, e.g.: man strtoul linux
>
>>
>>
>> I still fail to see why anyone wants to use this rather than a stream
>> or a lexical_cast. It's so C90.
>>
>> Is the preference due to performance, plain hatred of streams, or
>> something else?
>
> The former.

Among other things. strtofoo() has a simple, general interface, so if
you know how to use them, you can use them everywhere.

The only problem I've had is that they need a '\0'-terminated string.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

peter koch

unread,
Nov 5, 2014, 9:59:07 AM11/5/14
to
I must admit that I also like iostreams. The concept is fine even if performance might stink. But then conversion to/from string do not occur in any performance sensitive parts of my code. boost::lexical_cast does have very nice performance for the trivial stuff, by the way.

My dislike of strtoX functions is that they do not fit well with templates, that they are restricted to conversion from char* and that they have a to C-like interface.

/Peter

Erdoeban Zsukloff zu Brecher Zhuang

unread,
Nov 6, 2014, 9:51:24 PM11/6/14
to
> "Marcel Mueller" wrote in message news:m30vps$tan$1...@gwaiyur.mb-net.net...

> 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.

#include <stdio.h>
int main()
{ int i;
sscanf("0x80000000", "%i", &i);
printf("%x", i);
return 0;
}

> The goal is to read an unsigned number in all common formats (decimal,
> binary, octal, hex) from a string. The string does not necessarily end
> after the number. I did not find format specifier that does the job.

> Marcel

Are these numbers scattered all over the range, or are there a few specific
constants you're dealing with ? Because if latter (say, 0x80000000 shows up
80% of the time ...) , the fastest and arguably easiest way would be to test
for a pre-set (hardcoded ?) string ...


---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com

Öö Tiib

unread,
Nov 7, 2014, 4:13:35 AM11/7/14
to
On Friday, 7 November 2014 04:51:24 UTC+2, Erdoeban Zsukloff zu Brecher Zhuang wrote:
> > "Marcel Mueller" wrote in message news:m30vps$tan$1...@gwaiyur.mb-net.net...
>
> > 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.
>
> #include <stdio.h>
> int main()
> { int i;
> sscanf("0x80000000", "%i", &i);
> printf("%x", i);
> return 0;
> }
>
> > The goal is to read an unsigned number in all common formats (decimal,
> > binary, octal, hex) from a string. The string does not necessarily end
> > after the number. I did not find format specifier that does the job.
>
> > Marcel
>
> Are these numbers scattered all over the range, or are there a few specific
> constants you're dealing with ? Because if latter (say, 0x80000000 shows up
> 80% of the time ...) , the fastest and arguably easiest way would be to test
> for a pre-set (hardcoded ?) string ...

Does code written in GPU assembler contain major amount of constants
0x80000000? What you think?

Erdoeban Zsukloff zu Brecher Zhuang

unread,
Nov 14, 2014, 4:58:53 AM11/14/14
to
"嘱 Tiib" wrote in message
news:cacc6334-d051-46a0...@googlegroups.com...
Talking about the data, not the code. Why on earth would you infer code ? Or
is he _writing_ a GPU assembler - not something I understood from OP ...

Öö Tiib

unread,
Nov 14, 2014, 10:27:29 PM11/14/14
to
I have had impression (from this post and others) that Marcel is writing
GPU assembler.

Jorgen Grahn

unread,
Dec 7, 2014, 6:06:40 AM12/7/14
to
On Tue, 2014-11-04, Juha Nieminen wrote:
> Jouko Koski <joukokos...@netti.fi> wrote:
>> Well, the C standard library functions are in the global namespace already,
>> aren't they?
>
> I don't think you can rely on that. IIRC the newest gcc does not bring
> them to the global namespace if you use the <c...> versions.

I thought so too, but I cannot repeat it now. That's unfortunate -- I
really want as much as possible to stay away from the global namespace,
so I can use it myself.

Then there's the case where you're really using POSIX or Linux
versions of the headers rather than the basic C++ ones. Then IMO
you should definitelty use e.g. errno.h rather than cerrno.
0 new messages