I'm trying to replicate some printf
functionality for education purposes, but I've encountered some printf
behavior that I'm unable to understand. I'll try explaining with a simple example:
have this call:
printf(" %c %c %c", 0, 1, 2); // yes, parameters are ints not chars.
The output seems normal, only 3 spaces, numbers are ignored.
But taking printf
output to a file, then using "cat -e file" does this:
^@ ^A ^B
^@ for 0, ^A for 1, ^B for 2 and so on.
Here is my question, what are those symbols? How they relate to the values?
Also my own printf
, does this as well except for the 0 which is treated as a '\0' char...I need to mimic printf
exactly so I need to understand what is going on there...
I've searched about those symbols, but can't find anything. They are not memory garbage because the results are always same.
CodePudding user response:
The -e
option to cat
tells it to use a particular notation for printing non-printable characters. ^@
represents the value 0, ^A
represents the value 1, and ^B
represents the value 2. Those are exactly the values you gave.
CodePudding user response:
Simply cat uses caret notation to display not printable characters. ^A
represents 1 and ^Z
represents 26. ^@
is 0 and
- 27 -
^[
, - 28 -
^\
- 29 -
^]
- 30 -
^^
- 31 -
^_
- 127 -
^?
CodePudding user response:
What i meant is why
printf
prints ^@ while im getting '\0'(?)
printf("%c", 0);
prints the null character to stdout
. What you see when viewing the output of stdout
is not part of stdout
, but an implementation detail of the shell/terminal program. Print the return value of printf()
to get its understanding of how many characters it printed. Perhaps on stderr
to separate it from stdout
.
int count = printf(" %c %c %c", 0, 1, 2);
fprintf(stderr, "<%d>\n", count);
The output seems normal, only 3 spaces, numbers are ignored.
"Seems" deserves more detail. How was only 3 determined?
But taking printf output to a file, ...
What was the length of the file? 6?
... then using "cat -e file" does this:
Refer to @dbush good answer as to why you now see " ^@ ^A ^B".
is unclear as there is no memset()
in the question.
CodePudding user response:
Got it solved. Thanks to the explanations here, i realized that even i was printing the resulting string with write() i was using a pointer to iterate it so never gave a chance to actually pass over that null character.
write(STDOUT_FD, delta, d_length);
Then write() does the job correcty:
make test > check.txt && cat -e check.txt
own: ^@ ^A ^B$
lib: ^@ ^A ^B$
Also now i know about the caret notation, thanks everyone!