What does “shall be a pointer to the initial element of an array of character type” mean in C99 7.19 / C11 7.21?

StackOverflow https://stackoverflow.com/questions/18788489

Вопрос

The recent C standards specify that for printf("%s",p):

If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type

Does that mean that p must be compatible with char *, or should this sentence be interpreted in a more lenient fashion? Do other parts of the standard clarify what exactly is meant here by “an array of character type”?

Why this matters: If the phrase is interpreted strictly as meaning that p must be compatible with char *, an important consequence is that unsigned char *p; … printf("%s", p); is undefined on a compilation platform where char is signed, and const char *p; … printf("%s", p); is undefined.

Это было полезно?

Решение

The three types char, signed char, and unsigned char are collectively called the character types. ...
C11 6.2.5 15

So an array of "character type" would encompass these 3.

const, volatile, and restrict are qualifiers to various types and belong to the same type category. They apply too.

Any type so far mentioned is an unqualified type. Each unqualified type has several qualified versions of its type, corresponding to the combinations of one, two, or all three of the const, volatile, and restrict qualifiers. The qualified or unqualified versions of a type are distinct types that belong to the same type category and have the same representation and alignment requirements. A derived type is not qualified by the qualifiers (if any) of the type from which it is derived.
C11 6.2.5 26

Другие советы

Yes, p must be compatible with char. The main purpose of that line of text is likely to point out the distinction between char and wchar_t. It becomes clearer if you read further up in the same chapter (C11 7.21/7):

l (ell)
"Specifies... that a following s conversion specifier applies to a pointer to a wchar_t argument;"

If you write %ls, the argument must be compatible with wchar_t[], otherwise to char[].

As for char versus unsigned char: formally, a pointer to char is not compatible with a pointer to unsigned char. Passing an unsigned char* to printf("%s",p) is therefore formally undefined behavior.

However... in the real world outside the C standard, there exists no case where unsigned char cannot be used instead of char for the purpose of storing a character symbol. Simply because there exist no symbol tables with negative indices. ASCII, UTF8 and so on all start at 0 and count upwards from there. Your code will be 100% portable even though this is undefined behavior in theory

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top