#include <stdio.h>

int main()
{
    int sum = 0, result = (({for (int i = 0; i < 5; i++) sum += i;}), sum);
    
    printf("result = %d\n", result);

    return 0;
}

显示

result = 10

我使用的是GCC中C语言的默认版本.是专门针对GCC的吗?我知道(a, b)返回b,但当a{}块时,我没想到它会起作用.有没有人能解释它为什么起作用,为什么要用括号把它放在方块上才能使它起作用?

编辑:这是一个我正在试用的#define的人为简化的例子.一些程序员的 comments (谢谢)澄清了这一点.案子结案了.

推荐答案

我使用的是GCC中c的默认版本.

目前是-std=gnu17,相当于"带有GNU扩展的Lax ISO C17".这不是一种符合标准的模式,不建议初学者使用.

是专门针对GCC的吗?

是的,或者更确切地说,它是特定于GNU C方言的,至少clang也部分支持这种方言.正如注释中提到的,这是一个称为"语句表达式"或"表达式中的语句"的非标准扩展.它允许多个表达式/行,并可 Select 返回一个类似于函数的宏的值.

我知道(a,b)返回b,但当a是一个{}块时,我没想到它会起作用

逗号运算符具有特殊的求值规则,保证子表达式ab之前完全求值.通常情况下,C运算符并非如此.这意味着您可以假设a的所有代码都在b之前执行,甚至可以安全地包含使用b的代码.

However,要初始化的变量列表没有这样的排序保证.int sum = 0, result=sum;不保证任何特定的顺序或排序--这样的代码存在严重问题,而且可能是未定义的行为.


最佳实践是尽可能遵循标准C语言,编写尽可能可读的代码,并避免定义不明确的行为.复杂的"一行"代码是非常糟糕的做法.因此,这本应写成:

int sum = 0;
for (int i=0; i < 5; i++) 
{
  sum+=i;
}
int result = sum;

或者,如果你愿意,也可以是100%的类似功能:

int result = 10;

C++相关问答推荐

理解C中的指针定义

C/SDL程序,渲染不使用我的渲染器

GCC引发不明确的诊断消息

将 struct 变量赋给自身(通过指针取消引用)是否定义了行为?

模拟shell并运行.sh文件

Ruby C Api处理异常

C中函数类型的前向声明

轮询libusb_pollfd struct 列表的正确方式是什么?

C将数组传递给函数以修改数组

C语言中的数字指针

如何将两个uint32_t值交织成一个uint64_t?

如何对现有的双向循环链表进行排序?

GETS()在C++中重复它前面的行

如何在不更改格式说明符的情况下同时支持双精度和长双精度?

C编译和运行

即使我在C++中空闲,也肯定会丢失内存

为什么会出现此错误?二进制表达式的操作数无效

Dlsym()的手册页解决方法仍然容易出错?

C中的空指针是什么(_N)?

无法在线程内用 C 打印?