帮我理解这一小段代码

时间:2009-09-06 13:35:40

标签: c

我理解这段代码计算变量args的总和,但是,我不明白它是如何工作的。它对我来说看起来很抽象。有人可以解释下面的工作原理吗?

谢谢!

#include <stdio.h>

#define sum(...) \
    _sum(sizeof((int []){ __VA_ARGS__ }) / sizeof(int), (int []){ __VA_ARGS__ })

int _sum(size_t count, int values[])
{
    int s = 0;
    while(count--) s += values[count];
    return s;
}

int main(void)
{
    printf("%i", sum(1, 2, 3));
}

5 个答案:

答案 0 :(得分:21)

使用预处理器宏

#define sum(...) \
    _sum(sizeof((int []){ __VA_ARGS__ }) / sizeof(int), (int []){ __VA_ARGS__ })

使用sum(1,2,3)进行调用,该行被翻译(一个简单的字符串替换,将"__VA_ARGS__"替换为"1,2,3")到:

_sum(sizeof((int []){1,2,3}) / sizeof(int), (int []){1,2,3})

是对_sum()的函数调用,传递两件事:

  • 数组{1,2,3}中的整数数为3(通过将三整数数组的大小除以单个整数的大小得到此结果)。
  • 指向数组本身的指针(或者包含相同值的完全不同的数组,具体取决于编译器的智能程度)。

所有_sum()函数都会将每个整数添加到s(最初为零),直到计数用完为止。


上面的第一个要点有一些解释。当您有一个N元素数组定义如下:

tType x[22];

数组的大小为sizeof(x),即所有元素的大小。该数组的单个元素的大小为sizeof(x[0]),即第一个元素的大小,但我通常更喜欢sizeof(*x)变体。

因此,要计算元素数量,只需使用以下其中一项将总大小除以元素大小:

sizeof(x) / sizeof(x[0])
sizeof(x) / sizeof(*x)

而且,既然您已经要求对代码进行详细分析,那么我们就去了:

// Needed for printf().

#include <stdio.h>

// Macro to convert sum(n1,n2,...,nN) to _sum(N,n1,n2,...,nN).
// This calculates the length of the array by dividing its size by the size
//   of an int and passes both the length and array through to the new
//   function.
// __VA_ARGS__ is replaced with the entire marcro argument list, '1,2,3' in
//   this case.

#define sum(...) \
    _sum(sizeof((int []){ __VA_ARGS__ }) / sizeof(int), (int []){ __VA_ARGS__ })

// Function to take size and pointer to int array, and return sum.

int _sum (size_t count, int values[]) {
    int s = 0;                // Initial sum of zero.
    while(count--)            // Until elements exhausted (count down).
        s += values[count];   // Add each array element to accumulator.
    return s;                 // Return sum.
}

int main (void) {
    printf ("%i", sum(1, 2, 3));   // Test it with 1, 2 and 3 (should print 6).
}

答案 1 :(得分:4)

让我们看看宏

的示例调用sum(1, 2, 3)的扩展
#define sum(...) \
    _sum(sizeof((int []){ __VA_ARGS__ }) / sizeof(int), (int []){ __VA_ARGS__ })

...表示它是一个可变宏,即它需要任意数量的逗号分隔参数。在扩展时,特殊的预处理器令牌__VA_ARGS__将被这些参数替换,即

(int []){ __VA_ARGS__ }

扩展为

(int []){ 1, 2, 3 }

这是复合文字:C99允许通过这种类型化的初始化列表即时创建具有自动存储持续时间的对象。

重要的是推断出数组的大小:它不会有不完整的类型int [],但是类型为int [3],即

sizeof((int []){ 1, 2, 3 }) = sizeof(int [3]) = 3 * sizeof(int)

要获得元素数量,除以sizeof(int)

宏调用sum(1, 2, 3)因此等同于C90代码

int tmp[3] = { 1, 2, 3 };
_sum(3, tmp);

答案 2 :(得分:0)

在此代码中,sum宏通过使用sum(1,2,3)来计算元素数量_sum,将主要内容中的sizeof调用转换为对sum的调用被称为。具有三个值的int数组的大小将为3 * sizeof(int),因此除以sizeof(int)会再次产生三个。

答案 3 :(得分:0)

给定一个整数数组,它将汇总其所有元素并返回该值。

答案 4 :(得分:0)

此处的预处理器使用可变数量的参数variadic macro。 休息它只是从参数列表创建一个数组并操纵它