0
votes

I understand that %zd is the suggested way to format the sizeof result. However, I don't understand why that is necessary. For example using lu gives me the same output, and isn't the result of sizeof an unsigned long anyways? For example:

printf("Sizeof(char): %lu, Sizeof(short): %lu, Sizeof(int): %lu, Sizeof(long): %lu, Sizeof(long long): %lu, Sizeof(float): %lu, Sizeof(double): %lu, Sizeof(long double): %lu\n"
       ,sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long), sizeof(float), sizeof(double), sizeof(long double));
printf("Sizeof(char): %zd, Sizeof(short): %zd, Sizeof(int): %zd, Sizeof(long): %zd, Sizeof(long long): %zd, Sizeof(float): %zd, Sizeof(double): %zd, Sizeof(long double): %zd"
       ,sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long), sizeof(float), sizeof(double), sizeof(long double));

Sizeof(char): 1, Sizeof(short): 2, Sizeof(int): 4, Sizeof(long): 8, Sizeof(long long): 8, Sizeof(float): 4, Sizeof(double): 8, Sizeof(long double): 16
Sizeof(char): 1, Sizeof(short): 2, Sizeof(int): 4, Sizeof(long): 8, Sizeof(long long): 8, Sizeof(float): 4, Sizeof(double): 8, Sizeof(long double): 16

What's the reason or advantage of using %zd and why was that added in the first place?

2
The result of sizeof is a size_t, which may or may not be the same as an unsigned long, depending on the compiler, OS, and processor that you're using. And the format specifier is %zu, since size_t is unsigned. - user3386109
I wanna say because Microsoft... (but in reality they're probably not the only ones). - Siguza
@user3386109 I see, so is size_t something like typedef size_t int or typedef size_t <something-else> depending on the platform? - carl.hiass
Check this answer out. - Amal K
If size_t and unsigned long and unsigned int are all 32-bit size (and they can be), it does not matter whether you use %zu or %lu or %u, but the code is not portable. That's why you need to use the right specifier – so that printf() knows the size of the argument that is passed. All it has is a promise from the format specifier and must believe the caller passed the correct size operand. It has no other way of knowing, and is up to the programmer to match the format with the type. - Weather Vane

2 Answers

2
votes

isn't the result of sizeof an unsigned long anyways?

No, it returns a size_t, and a size_t needs not be the same size as an unsigned long.

For example, in the Windows world, an unsigned long is 32 bits and a size_t is 64 bits.

I understand that %zd is the suggested way to format the sizeof result.

Not quite.

Use %zu for size_t (or %zX, %zx or %zo)
Use %zd for ssize_t

Since sizeof returns a size_t, you want %zu.

1
votes

The value returned by the operator sizeof has the type size_t.

From the C Standard (6.5.3.4 The sizeof and alignof operators)

5 The value of the result of both operators is implementation-defined, and its type (an unsigned integer type) is size_t, defined in <stddef.h> (and other headers).

The type size_t is an implementation defined unsigned integer type. Usually it is defined as an alias for the type unsigned long though the C Standard does not require this. In particularly the Standard allows that the rank of the type size_t can be greater than the rank of the type unsigned long.

From the C Standard (7.19 Common definitions <stddef.h>)

4 The types used for size_t and ptrdiff_t should not have an integer conversion rank greater than that of signed long int unless the implementation supports objects large enough to make this necessary.

So to output values of the type size_t you should use the conversion specifier zu.