'Is it guaranteed by the C standard to be safe to do printf("%.*s", 0, NULL)?

I have a repeated print that prints a bunch of non null-terminated char*'s like so:

    int len1, len2, len3, len4;
    char *str1, *str2, *str3, *str4;
    get_vals(message, val1, &str1, &len1);
    get_vals(message, val2, &str2, &len2);
    get_vals(message, val3, &str3, &len3);
    get_vals(message, val4, &str4, &len4);
    printf("%.*s %.*s %.*s %.*s", len1, str1, len2, str2, len3, str3, len4, str4);

where get_vals sets the char * pointer to the value in memory and sets the len to the length of the text. It is possible for the passed in char * to be set to NULL, and if so, the length field will be set to 0. It seems this print has happened many times and not segfaulted, I assume due to the fact that the length specifier is 0 and so there is probably no dereferencing. However, is this always safe? Perhaps it is OS or libc version dependent? Is it worth doing a safety check like so:

    printf("%.*s %.*s %.*s %.*s",
           len1, str1 ? str1 : "",
           len2, str2 ? str2 : "",
           len3, str3 ? str3 : "",
           len4, str4 ? str4 : "");


Solution 1:[1]

Is it guaranteed by the C standard to be safe to do printf("%.*s", 0, NULL)?

No, not quite.

NULL is a implementation-defined null pointer constant. Its type may be void *, int, long, long long, unsigned, and a few other integer types. It is likely to be the same size and ... parameter compatible with char * or void*, but is not specified as such. Passing NULL to match a "%s" incurs a risk of undefined behavior.

Better to ask:

Is it guaranteed by the C standard to be safe to do printf("%.*s", 0, (char *) NULL)?

In this case, the answer by @David Grayson well applies: Technical undefined behavior, but often OK. [Although I do not abide by "This implies to me that it won't try to read any characters" as library implementations do not need to follow the rules of user code - they cheat.]


For high portability, do not use printf("%.*s", 0, NULL) for these 2 reasons.

Alternative:

printf("%.*s", 0, "");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1