#include <stdarg.h>
#include <stdio.h>

int ripple(int n, ...)
{
int i, j, k;
va_list p;

k = 0;
j = 1;
va_start(p, n);

for (; j < n; ++j)
{
i = va_arg(p, int);
for (; i; i &= i - 1)
++k;
}
va_end(p);
return k;
}

int main(void)
{
printf("%d\n", ripple(3, 5, 7));
return 0;
}

答案为:

5

The ​​va_arg​​​ macro produces the arguments passed as the “​​...​​​” part of a variadic function. In ​​ripple​​​ it will be called twice, setting ​​i​​ first to 5, then to 7.

The expression ​​i &= i - 1​​​ resets the right-most 1 bit in ​​i​​​. For example, if ​​i​​​ is 6 (binary 110), ​​i & i - 1​​​ is 4 (binary 100). The inner ​​for​​​ loop executes until ​​i​​​ is 0, so ​​k​​​ is increased by the number of 1 bits in ​​i​​.

There are two 1 bits in 5 (binary 101) and three in 7 (binary 111), so ​​ripple​​ returns 5.


这道题也是两个知识点,一个是可变参数函数定义以及如何实现,va_arg会把5,7依次取出来。另一个知识点是i &= i-1,实际上是计算了i二进制形式中1的个数,每次计算都会消减掉最低有效位上的1。比如7二进制表示为111。i &= i –1的计算结果依次为110,100, 000 (也就是0)。在hacker's Delights这本书里介绍了很多类似技巧。