本文介绍了在printf的顺序点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 这里我看了 的,有一个顺序点:However, when I run this code:int your_function(int a, int b) { return a - b;}int main(void) { int i = 10; printf("%d - %d - %d\n", i, your_function(++i, ++i), i);}Instead of what I expect I get:Meaning that there was not a sequence point created for the conversion format specifier. Is http://en.wikipedia.org wrong, or have I just misunderstood something, or is gcc non-compliant in this case (incidentally Visual Studio 2015 yields the same unexpected result)?EDIT:I understand that the order the arguments to your_function are evaluated and assigned to the parameters is undefined. I'm not asking about why my middle term is 0. I'm asking why the other two terms are both 12. 解决方案 Because this question was asked because of a comment-based discussion here, I'll provide some context:The OP accepts and understands this. No point in repeating the fact that your_function(++i, ++i) is UB.OP asking for clarification, so I elaborated a bit:That made it pretty clear that these kinds of constructs trigger UB for all functions.Wikipedia confusionOP Quotes this:Then applies it to his snippet (prinf("%d - %d - %d\n", i, your_function(++i, ++i), i);) expeciting the format specifiers to serve as sequence points.What is being referred to by saying "input/output conversion format specifier" is the %n specifier. The corresponding argument must be a pointer to an unsigned integer, and it will be assigned the number of characters printed thus far. Naturally, %n must be evaluated before the rest of the arguments are printed. However, using the pointer passed for %n in other arguments is still dangerous: it's not UB (well, it isn't, but it can be):printf("Foo %n %*s\n", &a, 100-a, "Bar");//DANGER!!There is a sequence point before the function is called, so the expression 100-a will be evaluated before %n has set &a to the correct value. If a is uninitialized, then 100-a is UB. If a is initialized to 0, for example, the result of the expression will be 100. On the whole, though, this kind of code is pretty much asking for trouble. Treat it as very bad practice, or worse...Just look at the output generated by either one of these statements:unsigned int a = 90;printf("%u %n %*s\n",a, &a, 10, "Bar");//90 Barprintf("%u\n", a);//3printf("Foo %u %n %*s\n",a, &a, 10-a, "Bar");//Foo 3 Bar < padding used: 10 - 3, not 10 - 6printf("%u\n", a);//6In as you can see, n gets reassigned inside of printf, so you can't use its new value in the argument list (because there's a sequence point). If you expect n to be reassigned "in-place" you're essentially expecting C to jump out of the function call, evaluate other arguments, and jump back into the call. That's just not possible. If you were to change unsigned int a = 90; to unsigned int a;, then the behaviour is undefined.Concerning the 12'sNow because the OP read up on sequence points, he correctly notices that this statement:printf("%d - %d - %d\n", i, your_function(++i, ++i), i);Is slightly different: your_function(++i, ++i) is a sequence point, and guarantees that i will be incremented twice. This function call is a sequence point because:That means that, before printf is called, your_function has to be called (because its return value is one of the arguments for the printf call), and i will be incremented twice.This could explain the output being "12 - 0 - 12", but is it guaranteed to be the output?NoTechnically, although most compilers will evaluate the your_function(++i, ++i); call first, the standard would allow a compiler to evaluate the arguments passed to sprintf left to right (the order isn't specified after all). So this would be an equally valid result:10 - 0 - 12//or even12 - 0 - 10//and10 - 0 - 10//technically, even this would be valid12 - 0 - 11Although the latter output is extremely unlikely (it'd be very inefficient) 这篇关于在printf的顺序点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-01 09:12