奇怪陈述中的优先级和数量
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 precendence。 year % 4
将被评估,结果将与 0 进行比较,然后结果将被分配给 leap
变量。
year % 4 == 0
等同于(year % 4) == 0
,取年除以4的余数,然后与0比较,得到布尔结果--true
或false
.您没有显示 leap
的 declaration/definition,因此我们只能猜测其类型。如果它是 bool
,则该结果将直接分配给它。基于后面的代码:
if (year%100 == 0 && year%400 != 0)
leap = 0;
看来 leap
可能是其他算术类型(可能是 int
)。这很常见,尤其是在最初用 C90 编写的代码中,它没有布尔类型。
在这种情况下,bool
将在赋值之前进行转换。转换为算术类型时,false
转换为0
,true
转换为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 整除)。
这条语句的执行顺序和可能的结果是什么: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 precendence。 year % 4
将被评估,结果将与 0 进行比较,然后结果将被分配给 leap
变量。
year % 4 == 0
等同于(year % 4) == 0
,取年除以4的余数,然后与0比较,得到布尔结果--true
或false
.您没有显示 leap
的 declaration/definition,因此我们只能猜测其类型。如果它是 bool
,则该结果将直接分配给它。基于后面的代码:
if (year%100 == 0 && year%400 != 0)
leap = 0;
看来 leap
可能是其他算术类型(可能是 int
)。这很常见,尤其是在最初用 C90 编写的代码中,它没有布尔类型。
在这种情况下,bool
将在赋值之前进行转换。转换为算术类型时,false
转换为0
,true
转换为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 整除)。