Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary operator inside printf

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.

like image 836
A.s. Bhullar Avatar asked Jul 02 '14 12:07

A.s. Bhullar


8 Answers

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.

like image 130
Shafik Yaghmour Avatar answered Oct 01 '22 16:10

Shafik Yaghmour


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.

like image 30
Wojtek Surowka Avatar answered Sep 30 '22 16:09

Wojtek Surowka


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.

like image 44
rom1nux Avatar answered Oct 01 '22 16:10

rom1nux


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.

like image 38
Abhinav Kathuria Avatar answered Sep 30 '22 16:09

Abhinav Kathuria


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);
like image 29
Rahul Tripathi Avatar answered Oct 01 '22 16:10

Rahul Tripathi


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);
like image 35
ThiefMaster Avatar answered Oct 01 '22 16:10

ThiefMaster


if(i>j)
    printf("%50s",str);
else
    printf("%s",str);

Therefore, Hello gets printed in both situations

like image 37
Ayush Avatar answered Sep 30 '22 16:09

Ayush


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;
}
like image 21
chux - Reinstate Monica Avatar answered Oct 03 '22 16:10

chux - Reinstate Monica