C printf中的三元算子

C printf中的三元算子,c,syntax,printf,conditional-operator,C,Syntax,Printf,Conditional Operator,读完这篇文章后,我开始想我已经学到了一些关于printf()的知识。突然,我发现了书中的以下代码片段: 令人惊讶的是,上面的代码运行时没有错误,并打印Hello。 据我所知,以下是printf()的语法: 因此,根据这种语法,printf()应该以格式字符串开头。但正如您在上面的代码中所看到的,printf()以i>j开头。 这是否意味着我在解释printf()的语法时出错了? 在printf()中放置三元运算符是一种特殊情况吗? 编辑 我知道关于三元运算符,我问的是printf()的第一个参数

读完这篇文章后,我开始想我已经学到了一些关于
printf()
的知识。突然,我发现了书中的以下代码片段:

令人惊讶的是,上面的代码运行时没有错误,并打印Hello。 据我所知,以下是
printf()
的语法:

因此,根据这种语法,
printf()
应该以格式字符串开头。但正如您在上面的代码中所看到的,
printf()
i>j
开头。 这是否意味着我在解释printf()的语法时出错了? 在printf()中放置三元运算符是一种特殊情况吗?

编辑

我知道关于三元运算符,我问的是
printf()
的第一个参数,它应该是const char*,在我的示例中似乎不是

这是否意味着我在解释printf()的语法时出错了

不,你没有理解错

在printf()中放置三元运算符是一种特殊情况吗

在C语言中,你可以说它是一个表达式而不是一个语句

您的代码相当于:

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

三元运算符只是一个内联
if
,用作表达式(而常规
if
用于创建块)。您的行等于:

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

此代码是正常的,不是任何特殊情况。
printf
的要求是第一个参数的类型应为
const char*
,但这并不一定意味着它需要像
“%s”
那样的字符串文字。这意味着您需要将类型为
const char*
的表达式作为第一个参数传递。和
i>j?”%50s:“%s”
满足此要求。

有一种形式的声明:条件?结果:备选方案

条件被检查,如果它是真的,你将得到结果。否则你会得到另一个选择

例如:

5>3 ? 10 : 5
5> 3是真的,所以你会得到10

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

因此,
Hello
在这两种情况下都会被打印出来

我认为您非常理解
printf
语法,但我认为您缺少一些关于C语法的内容

它存在一种形式的“compact IF like”语句,格式如下:(条件?true:false)

例如,您可以执行以下操作:

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) );
printf(i>j?"%50s":"%s",str);
在这种情况下,您可以看到:该值为true

以你为例:

int flag=1;
printf("The value is: %s", (flag!=0 ? "true" : "false) );
printf(i>j?"%50s":"%s",str);
如果i大于j,则使用“%50s”格式;如果i小于j,则使用“%s”格式

它可以是如下视图:

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

您可以看到紧凑测试的优点。

条件运算符:

i>j?"%50s":"%s"
是一个表达式,必须先对其求值,然后才能对函数调用本身求值。我们可以通过查看C99标准草案部分
6.5.2.2
函数调用来了解这一点,其中说明:

参数可以是任何对象类型的表达式。准备 对函数的调用、参数的求值以及每个 参数被赋予相应参数的值。81)

那么,条件运算符的求值结果是什么呢?如果我们转到第
6.5.15节
Conditional operator,它会说(强调我的):

计算第一个操作数;在其后面有一个序列点 评价仅当第一个操作数比较时,才计算第二个操作数 不等于0;仅当第一个操作数 比较等于0结果是第二个或第三个的值 操作数(以计算值为准),转换为所述类型 0.95以下


因此,在任何一种情况下,结果都是一个字符串文字,它将衰减为指向char的指针,该指针满足
printf

Q:这是否意味着我在解释printf()的语法时出错了?
答:不需要,只需要扩大允许的范围

问:在printf()中放置三元运算符是一种特殊情况吗?
答:没有。
?:
并不特别,但乍一看有时会令人困惑

提供给
printf()
的格式不需要是文本。它可以是任何字符串变量

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;
}

它是一个三元运算符,在这种情况下,条件i>j为false,因此%s将作为参数传递给printf,printf将打印字符数组的值,即hello。

第一个参数内的表达式的结果必须是指向常量字符数组的指针,所以没什么奇怪的。你的意思是,即使没有双引号,任何东西都是指向常量字符串的指针。如果你这样写的话,事情可能会变得更清楚:
printf((i>j?%50s):“%s”),str
@A.s.Bhullar这两个
%50s”
实际上都是指向常量字符数组的指针<代码>i>j?”%50s:“%s”是一个表达式。该表达式的结果必须是指向常量字符数组的指针。我想你把一个常量表达式与一个常量表达式混淆了,这两个表达式是不同的。你能举一个没有完全用双引号括起来的常量的例子吗?
I>j?”%50s:“%s”
const-char*
类型的(从技术上讲,它是
const-char[]
,但在这里并不重要)我想这就是你的例子。另一个例子是
func()
,其中
func
是一个返回
const char*
的函数。很好的解释!!但我仍然怀疑表达式I>j?“%50s”:“%s”即我不认为它是const char*,我认为它应该用双引号括起来。是吗?现在我明白了,在计算表达式之后,只有“%s”作为参数传递给printf()