tags:

views:

549

answers:

3

Very easy question for you Gurus but I haven't found the answer yet with about a good amount of searching.

I have some code that prints the amount of memory used by the program. The line is similar to this:

printf("The about of RAM used is %u", anIntVariable*sizeof(double) );

where anIntVariable is an int variable for the number of elements of the double array. Anyhow, on 32-bit systems I never had any problems but on 64-bit systems, I get a compiler warning about using "%u" for a unsigned long integer. Using "%lu" as the format code fixes the problem on 64-bit but causes the compiler to complain on 32-bit because the type is back to unsigned int. I've found that, indeed, sizeof(double) returns a different value on 32 vs 64 bit systems. I've found some webpage guides to convert code from 32 bit to 64 bit But I'd rather have code that works on both instead of just converting back and forth.

How do I write this line in a platform independent way? I know many ways I could do it using preprocessor directives but that seems like a hack. Surely there's an elegant way that I'm not realizing.

+7  A: 

Portable printf identifiers are provided in the include file inttypes.h.

This include file has many portable identifiers for your specific runtime. For your example, you want PRIuPTR, which means "PRintf Identifier unsigned with size of up to a pointer's size".

Your example will then be:

printf("The about of RAM used is %" PRIuPTR, anIntVariable*sizeof(double) );

Results on 64bit Linux with GCC 4.3 (int anIntVariable = 1):

$ gcc test.c -m32 -o test && ./test
The about of RAM used is 8
$ gcc test.c -o test && ./test
The about of RAM used is 8

For completeness sake, there are identifiers for scanf too, whose prefixes are SCN.

LiraNuna
I edited my answer with tested code this time :)
LiraNuna
This idea seems to answer my question. I've been programming in C for a number of years but my problems are normally practical, and things like portability rarely come up. I'm somewhat surprised at how architecture plays a role in such a simple situation. Thanks, Lira and Thomas too, who had a decent work-around solution, but this one seems to be the full answer.
Dr. Person Person II
+2  A: 

The return value of sizeof is a size_t. If you're using a C99 compliant compiler it looks like you can use %z for this.

wds
+4  A: 

First of all, you should match the "%" specifier with the actual data type you want to print. sizeof returns the data type size_t, and just as you shouldn't try to print a float using a "%d" specifier, you shouldn't try to print a size_t with "%u" or "%d" or anything that doesn't really mean size_t.

The other replies have given some good ways to handle this with newer compilers ("%z" and PRIu32), but the way we used to do this was simply to cast the size_t to unsigned long, and then print it using "%lu":

printf("The amount of RAM used is %lu", (unsigned long)(anIntVariable*sizeof(double)) );

This will not work on systems where size_t is wider than a long, but I don't know of any such systems, and I'm not even sure if the standard allows it.

Thomas Padron-McCarthy
Thomas. You're answer seems to work the best (under my current level of understanding. What caused the problem is that I was assuming that doing the (size_t) would inherit the type of anIntVariable but it doesn't. I'll keep the question open for a few more days and then mark this as the accepted answer. I still have yet to find the type promotion behavior of expressions containing (size_t), which is related to my question.
Dr. Person Person II
Note that win64 is a system where size_t is wider than a long.
Chris Jefferson