3

Suppose you have the following snippet of code:

include <stdio.h>
size_t nodeID = 5;
printf("nodeID = %lu", nodeID);

This will run without any warning being raised on a 64bit system but will generate a conversion warning for %lu on a 32bit system.

We can deal with it using the %z modifier

However this doesn't work on Visual Studio which uses the "I" modifier.

Is there any method available that solves this both in a architecture-independent and OS-independent way?

Community
  • 1
  • 1
bergercookie
  • 2,542
  • 1
  • 30
  • 38
  • Wouldn't it be better if `nodeID` did have the same size in all CPU environments? You could declare it `uint64_t` or `uint32_t` sothat the program doesn't change behaviour, if it isn't wanted that it runs differently on x86 and x64. – Maximilian Gerhardt Oct 23 '16 at 12:39
  • you could write your own print method with 10-division. – Jean-François Fabre Oct 23 '16 at 12:42
  • 2
    The `"%zu"` format is supposed to be the standard and independent way. Unfortunately the Visual Studio C compiler have to long skipped out on following standards. The last couple of releases (2013 and 2015) should have full C99 compatibility though. – Some programmer dude Oct 23 '16 at 12:44
  • If you want to write moder, standard compliant C code, the solution is simple: use a modern, standard compliant compiler and lib. MSVC and its standard library are not since 17 years and 2 versions of the standard. – too honest for this site Oct 23 '16 at 12:49
  • @Someprogrammerdude: 1) MS made very clear they will not support C99 resp. C features not available in C++, too. This includes VLAs for instance. 2) C standard is C11, which is already 5 years old now and they _stated_ (but not guaranteed) they want to support C11 only. Problem is e.g. VLAs were made optional in C11, despite the strong dedication of the commitee to backwards-compatibility - coincidence? Who knows ... – too honest for this site Oct 23 '16 at 12:52
  • @Olaf On one hand they claim full C99 conformance in the library ([reference](https://msdn.microsoft.com/en-us/library/hh409293.aspx#BK_CRT)) except if it's not supported by the Visual C++ compiler. On the other hand they specifically say that e.g. the `z` format prefix is not supported ([reference](http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx)) which sounds weird to me. Do they implement the formats in the compiler and not the library? – Some programmer dude Oct 23 '16 at 13:01
  • @Someprogrammerdude: `printf` format string is **completely** library-related. So how would the compiler be involved here? MS "claims" a lot. Just do a reality-check. `%zu` **is** part of the standard since version 1999, they don't support it: case closed. – too honest for this site Oct 23 '16 at 13:07

1 Answers1

5

As you say, you can use the z modifier:

#include <stdio.h>
size_t nodeID = 5;
printf("nodeID = %zu\n", nodeID);

though as you say IIRC this may have compatibility issues with old MS compilers. You may be able to get around this with something like:

#ifdef _MSC_VER /* Untested MSC detection */
#define PRIuSIZE Iu
#else
#define PRIuSIZE zu
#endif
#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)
#define USIZE_STR STR(PRIuSIZE)

#include <stdio.h>
size_t nodeID = 5;
printf("nodeID = %" USIZE_STR "\n", nodeID);

Another way, which is architecture and OS independent in the sense that it doesn't rely on conditional preprocessor macros in your files, would be:

#include <stdio.h>
#include <inttypes.h>
size_t nodeID = 5;
printf("nodeID = %" PRIu64 "\n", (uint64_t) nodeID);

This would obviously rely on size_t being smaller or equal to 64 bits in length, which I believe it always is.

bergercookie
  • 2,542
  • 1
  • 30
  • 38
abligh
  • 24,573
  • 4
  • 47
  • 84
  • 1
    "... I believe it always is." - Believe is a bad advisor for programming. There is no upper limit. Without `%zu` there is no fully compliant way - that's why `%zu` has been introduced. – too honest for this site Oct 23 '16 at 13:06
  • 1
    Because `size_t` can't be bigger the `uintmax_t`, you could coerce to `uintmax_t` and use `PRIuMAX` to get the correct format letters. But if you have the `` header and `uintmax_t`, the chances are high that you also have `%zu` available. Similar comments apply to `uint64_t` too. – Jonathan Leffler Oct 23 '16 at 16:58