如何在 C++ 预处理器宏中处理数组元素?

Posted

技术标签:

【中文标题】如何在 C++ 预处理器宏中处理数组元素?【英文标题】:How can I process array elements in a c++ preprocessor macro? 【发布时间】:2019-07-15 00:36:45 【问题描述】:

对于一个家庭作业,我们被要求编写一个预处理器宏来对数组的元素求和。

我的问题是,如何在宏中处理数组元素,使其可以扩展为总和(或对元素进行任何其他数学运算)?

我们的书中没有提到处理数组元素甚至访问它们,而且我在网上找不到很多有用的资源,因为宏不是处理此类事情的典型方法。我知道有更好的方法来做这样的事情,但我知道这样做是为了让我们更好地熟悉预处理器宏。

当我以函数的形式编写宏时,我不知道如何将总和“返回”给程序。我能想到的将宏扩展为总和的唯一方法是递归完成,我什至不确定是否可以使用宏进行递归。我写了一个宏,成功扩展为数组的大小,但我不确定从那里往哪个方向发展。

【问题讨论】:

C++ 还是 C?它们是非常不同的语言,具有非常不同的编程习惯用法和技术。 记住你可以写一个函数并在宏中调用这个函数。 这是高中还是大学级别的“C课程”?我可以 100% 肯定地说,就实际 C 或 C++ 而言,绝对不会从制作这样的宏中学到任何有用的编程技能。 用 const 表达式做这一切会比宏更好。 这有帮助吗? ***.com/questions/319328/… 【参考方案1】:

这是使用 c++14 的答案:

#include <array>
#include <iostream>
#include <numeric>
#include <type_traits>
#include <vector>

#define SUM(ARY) \
  std::accumulate( \
      std::begin(ARY), \
      std::end(ARY), \
      std::remove_reference_t<decltype(ARY[0])>)
int
main()

  auto ary1 = std::array< int, 5 >1,2,3,4,5;
  std::cout << SUM(ary1) << "\n";

  int ary2[] = 1,2,3,4,5;
  std::cout << SUM(ary2) << "\n";

  auto ary3 = std::vector< int >1, 2, 3, 4, 5;
  std::cout << SUM(ary3) << "\n";

  double ary4[] = 1.1,2.2,3.3,4.4,5.5;
  std::cout << SUM(ary4) << "\n";

请注意,您不会从宏中“返回”。宏是文本替换。在上面出现SUM(ary)的地方,它被替换为SUM(ARY)宏定义的扩展文本。

您可以将此扩展到其他操作:

#include <array>
#include <iostream>
#include <numeric>

#define OP_ON_ARY(ARY, OP) \
  std::accumulate( \
      std::next(std::begin(ARY)), \
      std::end(ARY), \
      *std::begin(ARY), \
      [](auto a, auto b)  return a OP b;  \
      )

int
main()

  auto ary = std::array< int, 5 >1,2,3,4,5;
  std::cout << OP_ON_ARY(ary, +) << "\n";
  std::cout << OP_ON_ARY(ary, -) << "\n";
  std::cout << OP_ON_ARY(ary, *) << "\n";

但是使用函数而不是宏更符合现代 c++ 的精神。

#include <array>
#include <iostream>
#include <numeric>
#include <vector>

template< typename Ary >
auto sum(Ary const & ary)

  return std::accumulate(
      std::begin(ary),
      std::end(ary),
      decltype(ary[0]));


int
main()

  auto ary1 = std::array< int, 5 >1,2,3,4,5;
  std::cout << sum(ary1) << "\n";

  int ary2[] = 1,2,3,4,5;
  std::cout << sum(ary2) << "\n";

  auto ary3 = std::vector< int >1, 2, 3, 4, 5;
  std::cout << sum(ary3) << "\n";

  double ary4[] = 1.1,2.2,3.3,4.4,5.5;
  std::cout << sum(ary4) << "\n";

【讨论】:

与其假设容器非空,不如使用操作符的标识值。见coliru.stacked-crooked.com/a/d0e87e6123fe1cac 这并不是他在作业中想要的,但我能够利用从您的解决方案中学到的知识来完成我的工作。谢谢!【参考方案2】:

预处理器本质上做了很多查找和替换操作。它没有任何真正高级的功能,当然也不知道数组是什么。我想这个任务要求你做的是编写一些内联代码来对数组或其他东西求和,然后为它创建一个宏。

#define fold(array, ln, acc, op) \
  for(size_t i = 0; i < ln; ++i) \
    acc = acc op array[i];

int main()
  int ar[10];
  int sum = 0;
  fold(ar, 10, sum, *); 

此代码使用* 操作折叠数组。

【讨论】:

我不知道您可以在宏中使用运算符作为参数。这很有趣,知道这件事可能很有用。

以上是关于如何在 C++ 预处理器宏中处理数组元素?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 停止预处理器宏扩展

使用预处理器宏组成另一个宏调用

Doxygen C预处理器宏文档样式

用引号定义C ++预处理器宏[重复]

MS Visual Studio 2010 C++ 预处理器 - 如果函数在宏中定义并在其他地方调用,未定义时是不是有任何开销

#if 和 #ifdef Objective-C 预处理器宏有啥区别?