This program exhibits unspecified behavior since the order of evaluation of sub expressions is unspecified except where it is specifically defined:
printf("%d",printf("hi!")*printf("bye"));
^ ^
1 2
So either 1 or 2 could be evaluated first and you can not determine which. We can see this from the C99 draft standard section 6.5 Expressions paragraph 3 which says (emphasis mine going forward):
The grouping of operators and operands is indicated by the syntax.74) Except as specified
later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.
Yes, printf does have a return value, which is the number of character printed or -1 if there is an error, in this case assuming no error the return value will be 3 for both the inner printfs
The arguments to a function are evaluated before the function is called which is why the inner printfs are executed first, this is covered in section 6.5.2.2 Function calls paragraph 4:
An argument may be an expression of any object type. In preparing for the call to a
function, the arguments are evaluated, and each parameter is assigned the value of the
corresponding argument.81)