在下面的代码中,根据我的说法,输出应为11 6 10
,但它会给出12 6 11
。自k=x
x>y
和x=10
以及y=6
,i=11
和{{1}以来由三位运算符返回的j=6
的值那么为什么产生的输出不匹配?
k=10
答案 0 :(得分:2)
扩展相当于:
k = (i++) > (++j) ? (i++) : (++j);
评估条件时,i
和j
都会增加(因此i
变为11
而j
变为6
。条件检查i
的原始值和j
和10 > 6
的递增值,i++
后的?
,k
被分配11
,i
增加到12。
因此输出应该是:
12 6 11
这里没有未定义的行为。在评估条件后,有一个完整的序列点。
另请注意,为了完全安全,宏应该在扩展周围有一组额外的括号:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
否则,你会得到奇数球效果:
int l = 7 * MAX(k, i) + 3;
有效;它只是没有按预期工作。
答案 1 :(得分:1)
输出按预期工作。您需要了解宏的扩展,并且不像复制输入参数的函数那样工作。
上述代码中MAX的定义是
let pickedDate: Date = sender.date
let NumOfDays: Int = daysBetweenDates(startDate: pickedDate, endDate: Date())
print("Num of Days: \(NumOfDays)")
所以
#define MAX(x, y) (x)>(y)?(x):(y)
扩展为
k = MAX(i++, ++j)
当i = 10且j = 5时,变量i增加两次。变量j只增加一次。
因此最终i = 12且j = 6,并且k = 11,因为三元运算符中的第二个操作数是后增量。
如果您使用的是gcc,那么在.c文件中运行 cpp 而不是 gcc 会很好地扩展宏。
除了Jonathan Leffler关于在宏中使用更多括号来表示安全性的评论之外,您可以考虑使用内联函数来避免这些意外结果。内联函数具有键入,按值传递和代码扩展的优点。
k = (i++)>(++j)?(i++):(++j)
有关详细信息,请参阅wiki。