Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output of printf out of order

Tags:

c

function

printf

I wrote the following:

#include <stdlib.h>
#include <stdio.h>
void ExecAsRoot (char* str);
int main ()
{
  printf ("Host real ip is:");
  ExecAsRoot("ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/'");
  return 0;
 }

void ExecAsRoot (char* str) {
  system (str);
}

My expected output is:

Host real ip is:7.17.11.29

While the actual output is:

7.17.11.29
Host real ip is:

Why is this?

like image 234
Joel G Mathew Avatar asked Aug 02 '17 18:08

Joel G Mathew


People also ask

What is %B in printf?

The Printf module API details the type conversion flags, among them: %B: convert a boolean argument to the string true or false %b: convert a boolean argument (deprecated; do not use in new programs).

What is %A in printf?

The %a formatting specifier is new in C99. It prints the floating-point number in hexadecimal form. This is not something you would use to present numbers to users, but it's very handy for under-the-hood/technical use cases. As an example, this code: printf("pi=%a\n", 3.14); prints: pi=0x1.91eb86p+1.

Does printf always print a new line?

The printf statement does not automatically append a newline to its output. It outputs only what the format string specifies. So if a newline is needed, you must include one in the format string.

How printf is executed?

Most of the compilers takes each parameter of printf() from right to left. So in the first printf() statement, the last parameter is x++, so this will be executed first, it will print 20, after that increase the value from 20 to 21. Now print the second last argument, and show 21.


1 Answers

The output of printf is being buffered because the string being printed does not contain a newline. As a result, the buffer does not get flushed until the program ends, and therefore appears after the output of the system command.

To flush the buffer, use fflush:

printf ("Host real ip is:");
fflush(stdout);
ExecAsRoot("ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/'");

If you want all writes to stdout to be unbuffered, you can use setvbuf to disable buffering:

setvbuf(stdout, NULL, _IONBF, 0);     // _IONBF = unbuffered

Or more simply:

setbuf(stdout, NULL);

Then all writes to stdout will appear immediately.

like image 79
dbush Avatar answered Oct 19 '22 00:10

dbush