warnings when dealing with format specifier %llu

226 Views Asked by At

Just a new programmer here.

I was experimenting with size_t and sizeof, specifically using them to find the size of an array, cause I was trying to make an array with the number of indexes be changeable.

Code:

int main() {

    int index = 0;

    printf("Enter size of an array: ");
    scanf("%d", &index);

    int MyArray[index];

    size_t capacity = sizeof(MyArray)/sizeof(MyArray[0]);

    printf("\nThe length of your array is: %llu", capacity);

    return 0;
}

And if you look at the printf statement, you can see that I used a format specifier which is %llu for long long unsigned int because (if I'm right) it was the data type of size_t.

But then it gives me multiple warnings like:

warning: unknown conversion type character 'l' in format [-Wformat=]|
warning: too many arguments for format [-Wformat-extra-args]|
2

There are 2 best solutions below

0
Eric Postpischil On

And if you look at the printf statement, you can see that I used a format specifier which is %llu for long long unsigned int because (if I'm right) it was the data type of size_t.

Clearly that is not right. Some C implementations may use long long unsigned int for size_t, but yours does not.

The C standard specifies a printf format flag for the size_t type, z, so %zu is a correct conversion specifier to use for size_t in any C implementation.

4
Vlad from Moscow On

As for the obtained warnings then this conversion specifier %llu as is is written correctly. Maybe these warnings are consequences of some other message that an incorrect conversion specifier with a value of the type size_t is used.

Also some very old compilers do not support types long long int and unsigned long long int.As a result the conversion specifier llu was not introduced.

However in any case you are using an invalid conversion specifier with a value of the type size_t.

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.

Usually the type size_t is defined as an alias for the type unsigned long int. The rank of the type unsigned long long int is greater than the rank of the type unsigned long int (that is the same as the rank of the type signed long int).

For example in Microsoft C the sizeof( unsigned long long int ) is equal to 8 while sizeof( unsigned long int ) and sizeof( size_t ) are equal to 4. And moreover the type size_t is defined as an alias for the type unsigned int instead of the usually used type unsigned long.

And from the C Standard (7.21.6.1 The fprintf function)

7 The length modifiers and their meanings are:

z Specifies that a following d, i, o, u, x, or X conversion specifier applies to a size_t or the corresponding signed integer type argument; or that a following n conversion specifier applies to a pointer to a signed integer type corresponding to size_t argument.

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

And

9 If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

Thus you should write

printf("\nThe length of your array is: %zu", capacity);
                                       ^^^^