奇怪陈述中的优先级和数量

Precedence & Arity in strange statement

这条语句的执行顺序和可能的结果是什么:leap = year%4 == 0;

(左边是赋值,右边是断言?) 这是用于计算公历中任何日期的星期几的以下算法的摘录:

static char daytab[2][13] =
{
                {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
                {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
for (year = 1; year <= y; year++)
{
        leap  = year%4 == 0;
        if (year%100 == 0 && year%400 != 0)
                leap = 0;
        for (month = 1; month <= m; month++)
        {
                d += daytab[leap][month - 1];
                daystotal = 365*(year - 1) + (int)floor((year-1)/4)
                - (int)floor((year - 1)/100) + (int)floor((year - 1)/400) + d;
        }
}

看这里operator precendenceyear % 4 将被评估,结果将与 0 进行比较,然后结果将被分配给 leap 变量。

year % 4 == 0等同于(year % 4) == 0,取年除以4的余数,然后与0比较,得到布尔结果--truefalse.您没有显示 leap 的 declaration/definition,因此我们只能猜测其类型。如果它是 bool,则该结果将直接分配给它。基于后面的代码:

if (year%100 == 0 && year%400 != 0)
    leap = 0;

看来 leap 可能是其他算术类型(可能是 int)。这很常见,尤其是在最初用 C90 编写的代码中,它没有布尔类型。

在这种情况下,bool 将在赋值之前进行转换。转换为算术类型时,false转换为0true转换为1(反之,0转换为false,任何其他值转换为 true).

因此,该代码与以下代码具有基本相同的效果:

if ((year % 4) == 0)
    leap = 1;
else
    leap = 0;

...或者:

leap = ((year % 4) == 0) ? 1 : 0;

如果我来写,我想我可能会这样写代码:

if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0) )
    leap = 1;
else
    leap = 0;

...或者(更有可能)只是:

leap = ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));

至少对我来说,这更直接地说明了公历1"what is a leap year"的情况。我想您可以通过以下方式将原始代码视为历史工件:它首先根据旧儒略历规则计算它是否是闰年,然后单独添加在公历中添加的规则。然而,如果有人真的想反映那段历史,他们可能应该包括一条注释,解释这就是代码按原样编写的原因。就目前而言,它不仅仅是计算正确的值,而是首先计算一个可能不正确的值,然后检查更多条件,然后修补该值。


1. 当然,它们是这样的:如果年份可以被 4 整除,并且不能被 100 整除,或者也可以被 400 整除,那么它就是闰年。因此,例如,2000 年是闰年(可以被 400 整除) 4 并且也可以被 400 整除)但是 1900 不能(可以被 4 整除,但也可以被 100 整除并且不能被 400 整除)。