printf 中的三元运算符

Posted

技术标签:

【中文标题】printf 中的三元运算符【英文标题】:Ternary operator inside printf 【发布时间】:2014-08-23 05:24:22 【问题描述】:

阅读this 后,我开始认为我学到了有关printf() 的知识。突然我从this book 中发现了以下代码 sn-p:

int main()

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

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

int printf(const char *format,argument_list);

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

编辑

我知道三元运算符我问的是printf() 的第一个参数,它应该是 const char* ,我在我的例子中似乎没有。

【问题讨论】:

第一个参数内的表达式的结果必须是一个指向常量字符数组的指针,所以没什么奇怪的。 你的意思是即使没有双引号也是指向常量字符串的指针 如果你这样写,事情可能会变得更清楚:printf((i>j?"%50s":"%s"), str) @A.s.Bhullar "%50s""%s" 实际上都是指向常量字符数组的指针。 i>j?"%50s":"%s" 是一个表达式。该表达式的结果必须是指向常量 char 数组的指针。我认为您将 const char * 与常量表达式混淆了,它们不是一回事 【参考方案1】:

条件运算符:

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

是一个表达式,它必须在函数调用本身被计算之前被计算。我们可以通过查看草案 C99 标准部分 6.5.2.2 函数调用 看到这一点:

参数可以是任何对象类型的表达式。在准备 对函数的调用,对参数进行评估,并且每个 参数被赋予相应参数的值。81)

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

计算第一个操作数;在它之后有一个序列点 评估。仅当第一个比较时才评估第二个操作数 不等于0;仅当第一个操作数被评估时,才评估第三个操作数 比较等于 0; 结果是第二个或第三个的值 操作数(以被评估者为准),转换为描述的类型 95

因此,无论哪种情况,结果都是一个字符串文字,它将衰减为指向 char 的指针,该指针满足 printf 的第一个参数的要求。

【讨论】:

很好的解释!!但是我仍然对表达式 i>j?"%50s":"%s" 表示怀疑,我认为它不是 const char* ,我认为它应该用双引号括起来。不是吗? 好的,现在我明白了,在评估表达式之后,只有“%s”作为参数传递给 printf()【参考方案2】:

这段代码是正常的,没有任何特殊情况。 printf 的要求是第一个参数应该是const char* 类型,但这并不一定意味着它必须是像"%s" 这样的字符串字面量。这意味着您需要将const char* 类型的表达式作为第一个参数传递。而i>j?"%50s":"%s" 满足了这一要求。

【讨论】:

你能举出任何没有完全包裹在双引号内的 const char* 的例子吗? i>j?"%50s":"%s"const char * 类型(技术上它是 const char [] 但在这里没关系)所以我想这是你的例子。另一个例子是func(),其中func 是一个返回const char* 的函数。【参考方案3】:

我认为您很了解 printf 语法,但我认为您缺少有关 C 语法的一些内容。

它存在一种“紧凑的 IF like”语句,格式如下:( condition ? 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);

如果 i 大于 j,则使用“%50s”格式,如果 i 小于 j,则使用“%s”格式

可以这样查看:

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

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

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

不,你没有解释错。

在 printf() 中放置三元运算符是特例吗?

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

您的代码相当于:

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

【讨论】:

【参考方案6】:

三元运算符只是用作表达式的内联if(而常规if 用于创建块)。你的行是这样的:

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

【讨论】:

【参考方案7】:
if(i>j)
    printf("%50s",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 ? "%50s" : "%s";
  printf(format, str);

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

【讨论】:

【参考方案9】:

有一个语句形式为:condition?consequent:alternative。

检查条件,如果为真,您将得到结果。否则,您将获得替代方案。

例如:

5>3 ? 10 : 5

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

【讨论】:

以上是关于printf 中的三元运算符的主要内容,如果未能解决你的问题,请参考以下文章

当printf用于三元运算符时,else条件会打印任何内容。为什么?

Java三元运算符关联性演示

python lambda表达式与三元运算

“ C”三元运算符返回变量时出错

Yaml 中的三元运算符

kotlin中的三元运算符[重复]