如何一个等于前pression工作printf的占位符? [英] How does an equal to expression work in a printf placeholder?

查看:163
本文介绍了如何一个等于前pression工作printf的占位符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的code片断:

I have the following code snippet:

main( )
{
int k = 35 ;
printf ( "\n%d %d %d", k == 35, k = 50, k > 40 ) ;
}

产生以下输出

0 50 0

我不知道我理解的的printf的的第一个值怎么来 0 。当 k值 35 ,它应该理想地返回(从而打印)1,但如何比较它打印零?另外两个值是已交出 50 0 都是正确的,因为在第二个值,值k设为 50 ,并为第三值 - k的值(即 35 )与比较 40 。由于 35℃ 40 ,所以它打印0。

I'm not sure I understand how the first value of the printf comes to 0. When the value of k is compared with 35, it should ideally return (and thus print) 1, but how is it printing zero? The other two values that are produced- 50 and 0 are all right, because in the second value, the value of k is taken as 50, and for the third value- the value of k(which is 35) is compared with 40. Since 35 < 40, so it prints 0.

任何帮助将是AP preciated,谢谢。

Any help would be appreciated, thanks.

**更新**

研究更多关于这个话题,并在未定义行为之后,我碰到这在一本书基于C来了,源代码是在末尾。

After researching more on this topic and also on undefined behavior, I came across this in a book on C, source is given at the end.

调用约定
调用约定指示哪些参数遇到函数调用时arepassed给函数的顺序。这里有两种可能性:

Calling Convention Calling convention indicates the order in which arguments arepassed to a function when a function call is encountered. There are two possibilities here:


  1. 参数可能会从左至右进行传递。

  2. 参数可能会由右至左过去了。

C语言如下二阶。

C language follows the second order.

考虑下面的函数调用:

fun (a, b, c, d ) ;

在此称之为无关紧要的参数是否被传递从左至右或者从右到左。然而,在一些函数调用传递参数成为一个重要的考虑的顺序。例如:

In this call it doesn’t matter whether the arguments are passed from left to right or from right to left. However, in some function call the order of passing arguments becomes an important consideration. For example:

int a = 1 ;
printf ( "%d %d %d", a, ++a, a++ ) ;

看来,这个的printf()将输出 1 2 3 。然而,这不是这种情况。出人意料的是,它输出 3 3 1

It appears that this printf( ) would output 1 2 3. This however is not the case. Surprisingly, it outputs 3 3 1.

这是因为C的调用约定是从右至左。即,首先 1 通过前pression A ++ 然后 A通过递增到 2 的一个++ 传递那么结果。也就是说, A 递增到 3 ,然后传递。最后,最新值 A ,即 3 ,被传递。因此,在从右到左的顺序 1,3,3 获得通过。一旦的printf()来收集这些信息将打印在开展我们要求它,让他们印刷(而不是他们所传递的顺序)的顺序。因此, 3 3 1 获取打印。

This is because C’s calling convention is from right to left. That is, firstly 1 is passed through the expression a++ and then a is incremented to 2. Then result of ++a is passed. That is, a is incremented to 3 and then passed. Finally, latest value of a, i.e. 3, is passed. Thus in right to left order 1, 3, 3 get passed. Once printf( ) collects them it prints them in the order in which we have asked it to get them printed (and not the order in which they were passed). Thus 3 3 1 gets printed.

**Source: "Let Us C" 5th edition, Author: Yashwant Kanetkar, Chapter 5: Functions and Pointers**


不管这个问题是否重复与否,我发现了这个新的信息,以便帮助我,所以决定分享。注意:这也支持Mr.Zurg在下面的意见psented索赔$ P $。


Regardless of whether this question is a duplicate or not, I found this new information to be helpful to me, so decided to share. Note: This also supports the claim presented by Mr.Zurg in the comments below.

推荐答案

不幸的是,所有这些谁读这本书,这是完全错误的。该草案C99标准显然让这个code未定义的行为。快速检查与未定义行为维基百科条目包含一个类似的例子,并确定它是不确定的。我不会离开它,但有一些得到这个权利,而不必求助于标准的其它方便的来源。

Unfortunately for all of those who read that book it is totally wrong. The draft C99 standard clearly make this code undefined behavior. A quick check with the Wikipedia entry on undefined behavior contain a similar example and identifies it as undefined. I won't leave it at that but there are other easily accessible sources that get this right without having to resort to the standard.

那么,是什么标准说什么?在第 6.5 防爆pressions 的段落的 3 的说道:

So what does the standard say? In section 6.5 Expressions paragraph 3 says:

运算符和操作数的分组是由syntax.74表示)
  除非以后指定(函数调用(),放大器;&放;, ||,:,和?
  逗号运营商),SUBEX pressions的评价和秩序
  在这种副作用的发生顺序都是不确定的。

The grouping of operators and operands is indicated by the syntax.74) Except as specified later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.

所以,除非指定的子前pressions的计算顺序是不确定的,进一步节 6.5.2.2 函数调用的段落的 10 的说道:

So unless specified the order of evaluation of sub-expressions is unspecified, and further section 6.5.2.2 Function calls paragraph 10 says:

功能指示符的评价的顺序,实际
  实际的参数内的参数和SUBEX pressions是
  未指定的,但实际的呼叫前一个序列点。

The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

因此​​,在你的例子:

So in your example:

printf ( "\n%d %d %d", k == 35, k = 50, k > 40 ) ;
         ^             ^        ^       ^
         1             2        3       4

子前pression 1〜4 以任何顺序可以评估,我们也没有办法知道,当从各子前$ P副作用虽然我们知道他们都具备的功能实际上是调用之前生效$ pssion会发生。

sub-expression 1 to 4 could be evaluated in any order and we have no way of knowing when the side effects from each sub-expression will take place although we know they all have to take effect before the function is actually called.

所以 K = 50 可能第一或最后或之间的任何地方进行评价和无论何时它被评估改变 K 可能需要与否,直到执行实际功能后立即到位。这意味着结果是未predictable可以想见,在不同的执行变化而变化。

So k = 50 could be evaluated first or last or anywhere in between and regardless of when it is evaluated the side effect of changing the value of k could take place immediately after or not until the actual function is executed. Which means the results is unpredictable could conceivably change change during different executions.

所以,接下来我们必须解决如何变得不确定的行为。这是覆盖在部分 6.5 段的 2 的它说:

So next we have to tackle how this becomes undefined behavior. This is covered in section 6.5 paragraph 2 which says:

在previous和下一个序列点的对象应具有其之间
  通过的评价最多一次修改储值
  前pression.72)而且,前值应只读到
  确定该值可以stored.73)

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.72) Furthermore, the prior value shall be read only to determine the value to be stored.73)

所以在你的例子中,我们不修改 K 不止一次,但我们使用的是以前的值做其他事情,除了确定该值将被存储。那么,什么是未定义行为的影响?在不确定的行为定义的标准说:

So in your example we are not modifying k more than once but we are using the prior value to do other things besides determine the value to be stored. So what are the implications of undefined behavior? In the definition of undefined behavior the standard says:

可能的不确定的行为是忽略的情况范围
  完全取消predictable成果,在翻译过程中的行为
  或执行程序中的一个记录方式的特点
  环境(有或没有发出一个诊断消息的),以
  终止翻译或执行(与发行的
  诊断消息)。

Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

所以编译器会忽略它或者也可能产生未predictable结果,其中涵盖了pretty各种不良行为。它臭名昭著有人说:

So the compiler could ignore it or could also produce unpredictable results, which covers a pretty wide range of undesirable behaviors. It has infamously been said that:

当编译器遇到[某一不确定的构造]它是合法的
  它使恶魔飞出你的鼻子

When the compiler encounters [a given undefined construct] it is legal for it to make demons fly out of your nose

这听起来pretty不可取给我。

which sounds pretty undesirable to me.

这篇关于如何一个等于前pression工作printf的占位符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆