Q:

Why my small C program print different string with cat utility?

#include <string.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
  char a[6] = "abcdd";
  char b[5] = "1234";

  strcpy(a, b);

  write(1, a, 4);
  printf("AA\n");
  write(1, b, 4);
  printf("CC\n");
}

I was studying strcpy func.
With ./a.out
1234AA
1234CC

With ./a.out | cat -e
12341234AA$
CC$

I read man cat. Can't find any with this.
What changes can be made even after compile?
What happened?
What are the concept I am missing?

A:

It's a buffering issue.
The write calls write directly to the standard output file descriptor. These writes are unbuffered.
The printf function writes to stdout which in normal cases (when stdout is connected to a terminal) are line-buffered (output is actually written on newline).
But when stdout is not connected to a terminal, like for example when you pipe the output, then the buffering scheme change. It becomes fully buffered. That means the buffer will only be written when explicitly flushed (or the buffer becomes full), which happens when the program exits.
Therefore the unbuffered output from write will be written first. Then when the program exits the stdout buffer will be written.
If you want the same behavior in both cases, you could explicitly flush the stdout buffer yourself:
write(STDOUT_FILENO, a, 4);
printf("AA\n");
fflush(stdout);

[Note that I changed the "magic number" 1 to the POSIX predefined symbol STDOUT_FILENO, which is typically easier to understand even when quickly glancing at the code.]

