• 10
• 10
• 12
• 12
• 14

# printf %03zu, crashes on windows.

This topic is 3555 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

a programmer i trusted told me when i am using a size_t variable i should use %zu to print it. Doing this took away my GCC warning on linux. I asked how he knew about %z, he said man printf. yet i never seen it there. That code, on windows crashes an access violation. That variable is still a size_t and the code runs perfectly on linux. Now that i change the %03zu to %03d and the code works perfectly on windows. whats really going on with %03zu?

##### Share on other sites
That 'z' is a new C99 specifier identifying (as you might have guessed..) a size_t type, 'u' on the other hand simply stands for unsigned and could've been used in place of that 'd' to properly print large values.

At any rate there's not much you can do portably about it portably, "%03Iu" would be the direct VC equivalent. You could print it as a long integer ("%03lu") and cast the input value to a long, though that might lose bits on e.g. Win64 where size_t 64-bits and long is only 32. If you merely want a unique identifier which doesn't risk loosing digits then printing it as a pointer ("%p") and casting the value to one would be another alternative.

Or you could always write your own conversion function..
void print_size_t(size_t value, signed width) { static const char table[] = "0123456789"; char digit = table[value % 10]; value /= 10; if(--width > 0 || value) {  print_size_t(value, width); } putchar(digit);}

edit: Oops.. Hopefully this printer works better.

[Edited by - implicit on August 1, 2008 5:51:04 AM]

##### Share on other sites
from what i know, long is 64bits on 64bit machines, long long still remains as 64bits also.

table is lame, i'd do digit = '0' + value % 10; ;)

do you have any idea why it crashes? maybe %z is not supported on windows? which makes me wonder, why isnt it ignored and not crash. Maybe it has to do with the other variables i feed (like if i did %s later and passed on int, thats bad. I wont be looking at that code until a few days from now).

##### Share on other sites
Quote:
 Original post by AcidZombie24from what i know, long is 64bits on 64bit machines, long long still remains as 64bits also.
As a general rule, yes. But long remains a 32-bit type on Win64 for backwards compatibility, but not on Linux for x64 for instance.

Quote:
 table is lame, i'd do digit = '0' + value % 10; ;)
As would I. But technically this is not guaranteed by the standard, though I have some doubts whether a machine where it wouldn't work even exists (it even works on EBCDIC-based IBM mainframes where the alphabet isn't contiguous).
I just figured some overzealous language lawyer would complain if I didn't.. ;)

Quote:
 do you have any idea why it crashes? maybe %z is not supported on windows? which makes me wonder, why isnt it ignored and not crash. Maybe it has to do with the other variables i feed (like if i did %s later and passed on int, thats bad. I wont be looking at that code until a few days from now).
It's a relatively new format specifier, from the C99 standard which isn't yet widely supported and which Microsoft in particular are notorious for not implementing. Unfortunately even GCC ports on Win32 (e.g. MingW) tend to use Microsoft's own standard library, so it won't work even when the compiler itself warns you to use it. This also causes trouble with all kinds of other specifiers like the new long long type and even plain old long double.

To be honest I don't know why it crashes from unknown specifiers, Microsoft generally tend to be fairly lenient in such cases and simply let you off with a warning. But perhaps it's in a debug version of the standard library? As a programmer I'd prefer it to crash loudly and hard rather than for such issues to be ignored, at least when developing.
Of course if it had actually tried to continue parsing other arguments at that point then, as you say, it might have confused an integer or a part of another argument with a pointer argument which in all likelihood would've lead to a crash.

##### Share on other sites
This all sounds like a perfectly good reason to use iostreams (and/or boost::format) instead.

##### Share on other sites
Quote:
 Original post by MaulingMonkeyThis all sounds like a perfectly good reason to use iostreams (and/or boost::format) instead.

Except that is C++ and from the sounds of it he is using C.

##### Share on other sites
Quote:
Original post by Cromulent
Quote:
 Original post by MaulingMonkeyThis all sounds like a perfectly good reason to use iostreams (and/or boost::format) instead.

Except that is C++ and from the sounds of it he is using C.

Perhaps, but if that is indeed the case, this sounds like a perfectly good reason to use C++ instead, and thus my original point still stands. From the sounds of it he is working on PC platforms where good C++ compilers are available.