重复完全相同的代码段1000次而不循环

时间:2019-04-30 16:34:31

标签: c c-preprocessor preprocessor

由于某种原因(与性能测量有关),我需要重复一个代码段1000次(也可以重复1024次),但是没有“ for”或任何其他循环。

很显然,我很可能会编写一个看起来像这样的宏:

#define RUN_1000_TIMES(x)   \
x                           \
x                           \
x                           \
...
...  /* (999+1 times the same line) */
...
x                           \
x

...然后将该宏应用于我的代码段。

但是有比1000行长的宏更好的解决方案吗?

5 个答案:

答案 0 :(得分:3)

#define RUN_1024_TIMES(x) do {RUN_512_TIMES(x); RUN_512_TIMES(x); } while(0)
#define RUN_512_TIMES(x) do {RUN_256_TIMES(x); RUN_256_TIMES(x); } while(0)
#define RUN_256_TIMES(x) do {RUN_128_TIMES(x); RUN_128_TIMES(x); } while(0)
#define RUN_128_TIMES(x) do {RUN_64_TIMES(x); RUN_64_TIMES(x); } while(0)
#define RUN_64_TIMES(x) do {RUN_32_TIMES(x); RUN_32_TIMES(x); } while(0)
#define RUN_32_TIMES(x) do {RUN_16_TIMES(x); RUN_16_TIMES(x); } while(0)
#define RUN_16_TIMES(x) do {RUN_8_TIMES(x); RUN_8_TIMES(x); } while(0)
#define RUN_8_TIMES(x) do {RUN_4_TIMES(x); RUN_4_TIMES(x); } while(0)
#define RUN_4_TIMES(x) do {RUN_2_TIMES(x); RUN_2_TIMES(x); } while(0)
#define RUN_2_TIMES(x) do {x; x; } while(0)

do{ ... } while(0)仅适用于用if (....) RUN_1024_TIMES(...);调用的情况。您可以在不需要时将其删除。

您也可以每个宏执行3次:

#define RUN_1000_TIMES(x) do {RUN_729_TIMES(x); RUN_243_TIMES(x); RUN_27_TIMES(x); x; } while(0)
#define RUN_729_TIMES(x) do {RUN_243_TIMES(x); RUN_243_TIMES(x); RUN_243_TIMES(x); } while(0)
#define RUN_243_TIMES(x) do {RUN_81_TIMES(x); RUN_81_TIMES(x); RUN_81_TIMES(x); } while(0)
#define RUN_81_TIMES(x) do {RUN_27_TIMES(x); RUN_27_TIMES(x); RUN_27_TIMES(x); } while(0)
#define RUN_27_TIMES(x) do {RUN_9_TIMES(x); RUN_9_TIMES(x); RUN_9_TIMES(x); } while(0)
#define RUN_9_TIMES(x) do {RUN_3_TIMES(x); RUN_3_TIMES(x); RUN_3_TIMES(x); } while(0)
#define RUN_3_TIMES(x) do {x; x; x; } while(0)

答案 1 :(得分:1)

在Python文件中,放入:

print("//header of the code")
for i in range(1000):
    print("x;")
print("//bottom of the code")

然后:

./gen.py > file.c

这将比您使用C预处理器所能做的要简单得多,它不能执行像循环这样的事情!

答案 2 :(得分:1)

FOO(FOO(FOO(X)))

请注意,您可以像语法那样在“调用”中递归“调用”宏(因此<com.google.android.material.navigation.NavigationView android:id="@+id/navigation_view" android:theme="@style/NavigationItemNoRipple" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:menu="@menu/menu_navigation" app:itemBackground="@drawable/custom_ripple"/> 可以);这是因为类似函数的宏调用的第一步使用了参数替换,它对递归没有限制。参数替换特别地涉及评估其对应参数出现在替换列表中(而不是字符串化或粘贴的一部分)的任何参数,就好像它本身在一行上一样,然后使用结果扩展替换每个此类参数。参数替换(和粘贴/字符串化)后,将在重新扫描并进一步替换步骤中重新扫描生成的替换列表。在步骤中,宏被标记为“蓝色颜料”(意味着,其他调用将被忽略)。类似于调用的递归完全是参数替换的功能,因此可以使用。

答案 3 :(得分:1)

您可以使用P99:http://p99.gforge.inria.fr/p99-html/group__preprocessor__for_gaec0c87b336a5fa2a8230e207af5cc1f0.html#gaec0c87b336a5fa2a8230e207af5cc1f0

“悲伤”部分是,可能是一个足够聪明的编译器...使其成为循环!

答案 4 :(得分:0)

您可以正常编写循环,然后只告诉编译器您希望展开循环。写得很好,就像写了1000行一样好。

执行此操作的方法取决于您的编译器。我将为我通常使用的编译器GCC写下答案,但其他编译器应该类似。

如果要展开代码中的所有循环,则比较容易:只需在命令行中添加一个或两个选项:

-funroll-loops
-funroll-all-loops

如果您想进一步了解这些选项的行为,请参阅编译器手册。在SO上也有关于它们的问题。

如果只想展开一个特定的循环并保留所有其他循环,则比较困难,但是也可以做到。检查该SO答案是否为:https://stackoverflow.com/a/14251545/6872717