简体   繁体   中英

Trying to replicate printf behaviour about variadic paramenters

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.

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.

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 - ^?

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".


I'm using memset to replace the character.

is unclear as there is no memset() in the question.

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM