由于某种原因(与性能测量有关),我需要重复一个代码段1000次(也可以重复1024次),但是没有“ for”或任何其他循环。
很显然,我很可能会编写一个看起来像这样的宏:
#define RUN_1000_TIMES(x) \
x \
x \
x \
...
... /* (999+1 times the same line) */
...
x \
x
...然后将该宏应用于我的代码段。
但是有比1000行长的宏更好的解决方案吗?
答案 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)
“悲伤”部分是,可能是一个足够聪明的编译器...使其成为循环!
答案 4 :(得分:0)
您可以正常编写循环,然后只告诉编译器您希望展开循环。写得很好,就像写了1000行一样好。
执行此操作的方法取决于您的编译器。我将为我通常使用的编译器GCC写下答案,但其他编译器应该类似。
如果要展开代码中的所有循环,则比较容易:只需在命令行中添加一个或两个选项:
-funroll-loops
-funroll-all-loops
如果您想进一步了解这些选项的行为,请参阅编译器手册。在SO上也有关于它们的问题。
如果只想展开一个特定的循环并保留所有其他循环,则比较困难,但是也可以做到。检查该SO答案是否为:https://stackoverflow.com/a/14251545/6872717