在C语言中,类似 "for(i=1;i<=10;printf("%d\n";i),i++)" 这样的写法是否合法且无未定义行为?

5
以下两个代码块完全相同并实现了相同的功能吗?当我运行程序时显示的是相同的内容,但我希望得到一些严谨的解释。
for(i=1;i<=10;i++)
{
printf("%d\n",i);
}

并且

for(i=1;i<=10;printf("%d\n",i),i++);
for循环期望参数是有效的C语句,不是吗?但即使我在StackOverflow上验证了像x+=4,y=x*2;这样的语句是安全的,因为逗号在这里作为序列点,对于在for循环中传递的printf("%d\n",i),i++)语句也是同样的道理吗?
如果是的话,请回答一下以下问题:
当一个语句涉及到多个逗号分隔的函数调用时,逗号是否会起到序列点的作用,如下所示: printf("Enter number\n"),scanf("%d",&number),printf("You entered %d",number);

4
是的,但是为什么你想要编写这样的代码?(逗号是序列点,只要不是函数调用内部的逗号)。 - nhahtdh
2
“for循环期望作为参数的是有效的C语句,不是吗?” 不是,它期望表达式。请参阅C99标准6.8.5:1。http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf - Pascal Cuoq
1
@SheerFish 在向别人询问之前,你尝试编译你的附加细节了吗?在我看来,这似乎是一个语法错误。 - Pascal Cuoq
1
@SheerFish,你是在说你有一个编译器可以接受 int a,b,*ptr,printf("Hello"),printf("Howdy"); 这样的代码吗?那这个编译器是哪个呢?编译器可能会因为各种原因(动态 UB 无法在编译时检测到、语言扩展等)而接受一些错误的程序,但是如果一个构造不被你的编译器所接受,你就不应该浪费时间来询问它。 - Pascal Cuoq
1
@SheerFish 很难用 C 语言的概念来解释一个不符合 C 语法的文本应该做什么。 - Pascal Cuoq
显示剩余7条评论
2个回答

3
这是完全有效的,对于编译器来说,两个语句都是相等的。但是对于读者来说,第二种格式几乎无法阅读,这是唯一的区别。使用第二种格式几乎没有任何意义。
逗号运算符引入了一个序列点。
参考: 6.5.17逗号运算符
段2: 逗号运算符的左操作数被评估为void表达式;在其评估和右操作数之间存在一个序列点。然后评估右操作数;结果具有其类型和值。114)

以下哪种技术原因可以解释为什么说下面语句是荒谬的 int a,b,*ptr,printf("Hello"),printf("Howdy");?如果用 (int a,b,*ptr),printf("Hello"),printf("Howdy"); 会有效吗? - Rüppell's Vulture

1
答案在C标准的6.8.5.3中:

1774 The statement

    for ( clause-1 ; expression-2 ; expression-3 ) statement

behaves as follows:

1775 The expression >expression-2 is the controlling expression that is evaluated before each execution of the loop body.

1776 The expression expression-3 is evaluated as a void expression after each execution of the loop body.

1777 If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions;

1778 it is reached in the order of execution before the first evaluation of the controlling expression.

1779 If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression.134)

1780 Both clause-1 and expression-3 can be omitted.

1781 An omitted expression-2 is replaced by a nonzero constant.

在执行printf语句和递增i之间建立了一个序列点。在这种情况下,printf语句和i是expression-3,而不是条件语句,因此该语句虽然不是最佳实践,但是有效的。

以下哪个是技术上说下面的语句 int a,b,*ptr,printf("Hello"),printf("Howdy"); 是荒谬的原因?如果使用 (int a,b,*ptr),printf("Hello"),printf("Howdy");,它是否有效? - Rüppell's Vulture
@SheerFish:这与我写 int a,b,c = 0; 没有什么不同。逗号运算符的作用是相同的。我的例子中不同之处在于赋值操作。虽然你的例子不太易读。 - user195488
我应该再提出另一个问题吗? - Rüppell's Vulture

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接