Троичный оператор внутри printf

#c #syntax #printf #conditional-operator

#c #синтаксис #printf #условный оператор

Вопрос:

После прочтения этого я начал думать, что узнал много интересного printf() . Внезапно я обнаружил следующий фрагмент кода из этой книги:

 int main()
{
    char str[]="Hello";
    int i=5,j=10;
    printf(i>j?"Ps":"%s",str); //unable to understand this 
    return 0;
}
  

Удивительно, что приведенный выше код выполняется без ошибок и выводит привет.
Насколько мне известно, ниже приведен синтаксис printf() :

 int printf(const char *format,argument_list);
  

Итак, согласно этому синтаксису, printf() должен начинаться со строки формата. Но, как вы можете видеть в приведенном выше коде, printf() начинается с i>j .
Означает ли это, что я ошибаюсь в интерпретации синтаксиса printf()? Является ли размещение троичного оператора внутри printf() особым случаем?

Редактировать

Я знаю о троичном операторе, я спрашиваю о первом аргументе printf() , который должен быть const char *, которого, как мне кажется, нет в моем примере.

Комментарии:

1. Результатом выражения внутри 1-го параметра должен быть указатель на постоянный массив символов, так что ничего удивительного.

2. вы имеете в виду, что все, что даже без двойных кавычек, является указателем на постоянную строку

3. может быть, все станет понятнее, если вы напишете это таким образом: printf((i>j?"Ps":"%s"), str)

4. @A.s.Bhullar оба "Ps" и "%s" на самом деле являются указателями на постоянные массивы символов. i>j?"Ps":"%s" является выражением. Результатом этого выражения должен быть указатель на постоянный массив символов. Я думаю, вы путаете const char * с постоянным выражением, что не одно и то же

Ответ №1:

Условный оператор:

 i>j?"Ps":"%s"
  

является выражением, и оно должно быть вычислено до того, как может быть вычислен сам вызов функции. Мы можем убедиться в этом, перейдя к проекту стандартного раздела C99 « 6.5.2.2 Вызовы функций«, в котором говорится:

Аргументом может быть выражение любого типа объекта. При подготовке к вызову функции вычисляются аргументы, и каждому параметру присваивается значение соответствующего аргумента.81)

Итак, каков результат вычисления условного оператора? Если мы перейдем к разделу 6.5.15 Условный оператор, он говорит (курсив мой):

Вычисляется первый операнд; после его вычисления есть точка последовательности. Второй операнд вычисляется, только если первое сравнение не равно 0; третий операнд вычисляется, только если первое сравнение равно 0; результатом является значение второго или третьего операнда (в зависимости от того, что вычисляется), преобразованное в тип, описанный ниже.95

таким образом, в любом случае результатом является строковый литерал, который будет распадаться на указатель на char, который удовлетворяет требованию для первого аргумента printf .

Комментарии:

1. Хорошее объяснение!! Но я все еще сомневаюсь в выражении i> j?»Ps»:»%s» то есть я не думаю, что это const char * , я думаю, что это должно быть заключено в двойные кавычки. Разве это не так?

2. Хорошо, теперь я понимаю, что после вычисления выражения в качестве аргумента printf() передается только «%s»

Ответ №2:

Этот код является обычным и не является каким-либо особым случаем. Требование для printf заключается в том, что первый аргумент должен иметь тип const char* , но это не обязательно означает, что он должен быть строковым литералом типа "%s" . Все это означает, что вам нужно передать в качестве первого аргумента выражение типа const char* . И i>j?"Ps":"%s" выполняет это требование.

Комментарии:

1. Можете ли вы, пожалуйста, привести какой-либо пример const char *, который не полностью заключен в двойные кавычки?

2. i>j?"Ps":"%s" имеет тип const char * (технически это так const char [] , но здесь это не имеет значения), поэтому я думаю, что это ваш пример. Другим примером может быть func() , где func — возвращаемая функция const char* .

Ответ №3:

Я думаю, вы хорошо поняли printf синтаксис, но я думаю, что вам чего-то не хватает в синтаксисе C.

Существует форма инструкции «compact IF like», отформатированная следующим образом: ( условие? истина : ложь )

Например, вы можете сделать :

 int a=5;
int b=(a==5 ? 128 : 256);
int c=(a!=5 ? 8 : 9);
  

В этом случае b=128 и c=9.

Другой пример :

 int flag=1;
printf("The value is: %s", (flag!=0 ? "true" : "false) );
  

В этом случае вы можете видеть: значение равно true

На вашем примере :

 printf(i>j?"Ps":"%s",str);
  

если значение i выше, чем j, вы используете формат «Ps», а если значение i ниже, вы используете формат «%s»

Это может быть вид, подобный :

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

Вы можете видеть преимущество компактного теста.

Ответ №4:

Это троичный оператор, и в этом случае условие i> j равно false, поэтому %s будет передан в качестве параметра в printf, который выведет значение массива символов, которое является hello.

Ответ №5:

Означает ли это, что я ошибаюсь в интерпретации синтаксиса printf()?

Нет, вы не интерпретируете это неправильно.

Является ли размещение троичного оператора внутри printf() особым случаем?

В C вы можете сказать, что это выражение, а не оператор

Ваш код эквивалентен:

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

Ответ №6:

Троичный оператор — это просто встроенный, if который используется как выражение (в то время как обычный if используется для создания блока). Ваша строка равна этому:

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

Ответ №7:

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

Следовательно, Hello печатается в обеих ситуациях

Ответ №8:

В: Означает ли это, что я ошибаюсь в интерпретации синтаксиса printf()?
A: Нет, просто нужно расширить то, что допустимо.

Вопрос: Является ли размещение троичного оператора внутри printf() особым случаем?
A: Нет ?: не является чем-то особенным, но на первый взгляд иногда сбивает с толку.

Формат, предоставляемый printf() , не обязательно должен быть литералом. Это может быть любая строковая переменная.

 int main() {
  char str[]="Hello";
  char *format;
  int i,j;

  i = 5; j = 10; 
  format = i > j ? "Ps" : "%s";
  printf(format, str);

  i = 10; j = 5; 
  format = i > j ? "Ps" : "%s";
  printf(format, str);
  return 0;
}
  

Ответ №9:

Существует оператор вида: условие?следствие:альтернатива.

Условие проверяется, и если оно верно, вы получите результат. в противном случае вы получите альтернативу.

Например:

 5>3 ? 10 : 5
  

значение 5> 3 равно true, поэтому вы получите 10.