C语言中含双增量的for循环表达式是否符合标准定义?
你的循环代码违反C标准,属于未定义行为
首先直接给结论:你写的for (int j=0; j < t; j += (++j) & m)完全不符合C语言标准,因为同一个表达式里对j进行了两次无序列点的修改操作——+=会修改j,++j也会修改j,这两个操作的执行顺序没有被标准规定,编译器可以任意安排,最终运行结果完全不可预测,属于典型的未定义行为,绝对不能用。
举个实际例子:假设当前j=3,m=4(2的幂),编译器可能先算++j得到4,再算4&4=4,最后j +=4让j变成8;但也有可能先读取j的初始值3,算完(++j)&m得到4后,直接执行3+4=7赋值给j,两种结果天差地别,这就是未定义行为的风险。
符合需求的正确写法
你的核心需求是遍历[0, t)中所有不满足j&m !=0的整数(也就是跳过所有第k位为1的数,因为m是2的幂,对应二进制里唯一的1位),这里给两种靠谱的写法:
写法1:直观判断跳过(可读性拉满)
最简单也最不容易出错的写法,哪怕新手也能看懂:
for (int j = 0; j < t; ++j) { if ((j & m) != 0) { continue; } // 这里写你的业务逻辑 }
写法2:位运算高效跳转(贴合你的原始思路)
如果想避免每次判断,直接跳过整个不符合要求的区块,可以利用m是2的幂的特性,直接计算下一个合法的j:
int j = 0; while (j < t) { // 处理当前j if ((j + 1) & m) { // j+1的m位被置位了,直接跳到下一个无m位的区间起点 j = (j | m) + 1; } else { // 下一个数合法,直接自增 j++; } }
举个例子验证:假设t=16,m=4(二进制100),合法的数是0-3、8-11:
- 当
j=3时,j+1=4,4&4≠0,所以j=(3|4)+1=7+1=8,直接跳过4-7的所有数; - 当
j=8时,j+1=9,9&4=0,所以j++变成9,依次处理8-11。
这个写法既符合C标准,又实现了你想要的高效跳过逻辑。
内容的提问来源于stack exchange,提问作者Thomas Baruchel
相关产品推荐
相关产品推荐

