1

Does s conversion specifier specify direction / order in which characters are written?

N3220 working draft, 7.23.6p8 (emphasis added):

s If no l length modifier is present, the argument shall be a pointer to storage of character type.326) Characters from the storage are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the storage, the storage shall contain a null character.

Does it mean that the following program:

#include <stdio.h>

int main(void)
{
    char s[] = {'x', '\0', 'y'};
    printf("%s", s);
}

is allowed to print y?

Despite that the writing direction / order is perhaps obvious, is it specified?

4
  • 2
    "up to" means that it goes in increasing order of indexes. So it starts from index 0, keeps incrementing until it gets to the null byte. Commented Jun 24, 2024 at 19:29
  • Which means left-to-right. Commented Jun 24, 2024 at 19:30
  • 1
    Related? How do you output in languages that are read from right to left? Commented Jun 24, 2024 at 21:39
  • @WeatherVane Perfectly related. Thanks. Commented Jun 25, 2024 at 14:05

3 Answers 3

4

is allowed to print y?

No, not with that code.

Given, char s[] = { various};, with printf("%s", s);, the array s is converted to the address of the the first array element. So printf() receives a pointer and has no idea of the size of array s.

"Characters from the storage are written up to ..." implies that the pointer is incremented for subsequent characters.

The number of characters continues until a null character is encountered (that null character is not printed). Characters in s[] after the null character are not printed nor are they accessed.


If a precision specifier is use, the termination of printings stops when a null character is encountered or the specifier count of characters has printed.

Thus code can print the 'y' even though it lacks a following null character.

char s[] = { char s[] = {'x', '\0', 'y' };
printf("%.*s", 1, s + 2);
// or
printf("%.1s", s + 2);

Despite that the writing direction / order is perhaps obvious, is it specified?

The writing direction on the screen (left-to-right, right-to-left, etc.) is a function of the terminal interface. Overwhelmingly, it is left-to-right. This and other terminal characteristics like font size, typeface, color are terminal specific. Text output on such devices, especially multilingual, ones allow for R-to-L as well. Such I/O details are not part of C.

The order of processing characters, from lowest address to highest, is specified by C.

Sign up to request clarification or add additional context in comments.

3 Comments

even though it lacks a following null character. – don't you need a period to limit the output length as in "%.1s"? Your "%1s" defines the (minimum) field width, not the maximum string length to use, and the source string needs a terminator.
@WeatherVane Yes, even though I wrote precision, my code example was in error. Code amended.
Thanks. I've mixed the semantics of "up to" with the semantics of "until".
0

The conversion specifier s is designed to output a string: a sequence of characters terminated by a null character ('\0').

So this call of printf

printf("%s", s);

for the character array s declared like

char s[] = {'x', '\0', 'y'};

will output the character 'x' because the array contains string { 'x', '\0' }or in other representation "x".

That is according to the quote

Characters from the storage are written up to (but not including) the terminating null character

If you will specify a precision like for example

printf("%.10s", s);

then again according to the quote there will be outputed the string "x".

The character 'y' will not be outputed in any case because it is present outside the stored string in the array.

Nevertheless, if you want to output the character 'y' using the conversion specifier s that is present in the array s outside the stored string you can write

printf("%.1s", s + 2);

On the other hand, if the array contains for example the following characters

char s[] = {'x', 'y', '\0' };

and you want to output only the character 'x' using the conversion specifier s you can specify the precision similarly as shown above like

printf("%.1s", s);

That is the precision allows to output a part of a string.

15 Comments

DV without a reason, hmm - seems unfair for this answer.
I didn't DV, but where does this say that the array is processed left-to-right, which is the OP's question?
@chux-ReinstateMonica Thanks, you are a kind person.:)
@Barmar There is written in the provided quote shown in my answer.
But chux's answer makes it very clear why it has to be that way -- because passing an array to a function converts to the address of index 0.
|
0
    char s[] = {'x', '\0', 'y'};
    printf("%s", s);

s is an array of three char values, that is filled as specified above. When s is passed to printf() the routine interprets the passed value (a pointer to the first element with loss of information about where the pointer is pointing actually --- a string literal, a char * or a char [3] which decays to char *. It will search and print characters from the first of the array, until it sees a C string terminator (being this '\0' at position 1 in the array) So this will always print x, despite of what comes behind.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.