After reading this I started thinking that I have learned a loot about printf()
. Suddenly I found following code snippet from this book:
int main()
{
char str[]="Hello";
int i=5,j=10;
printf(i>j?"%50s":"%s",str); //unable to understand this
return 0;
}
Surprisingly above code is running without errors and it prints Hello.
As per my knowledge following is syntax of printf()
:
int printf(const char *format,argument_list);
So according to this syntax, printf()
should start with format string. But as you can see in above code printf()
is starting with i>j
.
Does it mean I am wrong in interpreting syntax of printf()?
Does placing ternary operator inside printf() is a special case?
EDIT
I know about ternary operator I am asking about first argument of printf()
which should be const char* which I seem not in my example.
The conditional operator:
i>j?"%50s":"%s"
is an expression and it has to be evaluated before the function call itself can be evaluated. We can see this by going to the draft C99 standard section 6.5.2.2
Function calls which says:
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)
So what is the result of the evaluation of the conditional operator? If we go to section 6.5.15
Conditional operator it says (emphasis mine):
The first operand is evaluated; there is a sequence point after its evaluation. The second operand is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0; the result is the value of the second or third operand (whichever is evaluated), converted to the type described below.95
so in either case the result is a string literal which will decay to pointer to char which satisfies the requirement for the first argument to printf
.
This code is normal and is not any special case. The requirement for printf
is that the first argument should be of the type const char*
, but it does not necessarily mean that it needs to be a string literal like "%s"
. All it means that you need to pass as the first argument an expression of the type const char*
. And i>j?"%50s":"%s"
fulfils this requirement.
I think you well understood the printf
syntax but i think you are missing something about C syntax.
It exist a form of "compact IF like" statement formatted like that : ( condition ? true : false )
For example you can do :
int a=5;
int b=(a==5 ? 128 : 256);
int c=(a!=5 ? 8 : 9);
In this case, b=128 and c=9.
An other example :
int flag=1;
printf("The value is: %s", (flag!=0 ? "true" : "false) );
In this case you can see : The value is true
On your example :
printf(i>j?"%50s":"%s",str);
if i is upper than j you use "%50s" format and, if i is lower you use "%s" format
It can be view like :
if (i>j)
printf("%50s",str);
else
printf("%s",str);
You can see the advantage of compact test.
It is a ternary operator and in this the condition i>j is false so %s will be passed as parameter to printf which will print the value of character array which is hello.
Does it mean I am wrong in interpreting syntax of printf()?
No you are not interpreting it wrong.
Does placing ternary operator inside printf() is a special case?
In C, you can say that its an expression instead of a statement
Your code is equivalent to:
if (i > j)
printf("%50s", str);
else
printf("%s", str);
The ternary operator is simply an inline if
that's used as an expression (while a regular if
is used to create a block). Your line is equal to this:
if (i > j)
printf("%50s", str);
else
printf("%s", str);
if(i>j)
printf("%50s",str);
else
printf("%s",str);
Therefore, Hello
gets printed in both situations
Q: Does it mean I am wrong in interpreting syntax of printf()?
A: No, just need to expand what is allowable.
Q: Does placing ternary operator inside printf() is a special case?
A: No ?:
is not special, but sometimes confusing at first glance.
The format supplied to printf()
does not need to be a literal. It may be any string variable.
int main() {
char str[]="Hello";
char *format;
int i,j;
i = 5; j = 10;
format = i > j ? "%50s" : "%s";
printf(format, str);
i = 10; j = 5;
format = i > j ? "%50s" : "%s";
printf(format, str);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With