所以我通过展开一些循环来优化一些代码(是的,我知道我应该依靠我的编译器为我做这个,但我不会选择我的编译器)我想这样做有点优雅,以防万一我的数据大小由于将来的某些编辑而发生变化,代码会优雅地降级。
类似的东西:
typedef struct {
uint32_t alpha;
uint32_t two;
uint32_t iii;
} Entry;
/*...*/
uint8_t * bytes = (uint8_t *) entry;
#define PROCESS_ENTRY(i) bytes[i] ^= 1; /*...etc, etc, */
#if (sizeof(Entry) == 12)
PROCESS_ENTRY( 0);PROCESS_ENTRY( 1);PROCESS_ENTRY( 2);
PROCESS_ENTRY( 3);PROCESS_ENTRY( 4);PROCESS_ENTRY( 5);
PROCESS_ENTRY( 6);PROCESS_ENTRY( 7);PROCESS_ENTRY( 8);
PROCESS_ENTRY( 9);PROCESS_ENTRY(10);PROCESS_ENTRY(11);
#else
# warning Using non-optimized code
size_t i;
for (i = 0; i < sizeof(Entry); i++)
{
PROCESS_ENTRY(i);
}
#endif
#undef PROCESS_ENTRY
当然,这不起作用,因为预处理器无法使用sizeof
(至少,这是this answer似乎表示的内容)。
我是否可以使用简单的解决方法来获取用于C宏的sizeof
数据结构,或者我只是SOL?
答案 0 :(得分:17)
您不能在预处理器中执行此操作,但您不需要。只需在宏中生成一个简单的if
:
#define PROCESS_ENTRY(i) bytes[i] ^= 1; /*...etc, etc, */
if (sizeof(Entry) == 12) {
PROCESS_ENTRY( 0);PROCESS_ENTRY( 1);PROCESS_ENTRY( 2);
PROCESS_ENTRY( 3);PROCESS_ENTRY( 4);PROCESS_ENTRY( 5);
PROCESS_ENTRY( 6);PROCESS_ENTRY( 7);PROCESS_ENTRY( 8);
PROCESS_ENTRY( 9);PROCESS_ENTRY(10);PROCESS_ENTRY(11);
} else {
size_t i;
for (i = 0; i < sizeof(Entry); i++) {
PROCESS_ENTRY(i);
}
}
sizeof
是一个常量表达式,将常量与常量进行比较也是常量。任何理智的C编译器都会优化掉在编译时始终为false的分支 - 常量折叠是最基本的优化之一。但是你失去了#warning
。
答案 1 :(得分:9)
如果您正在使用autoconf或其他构建配置系统,则可以在配置时检查数据结构的大小并写出标头(如#define SIZEOF_Entry 12
)。当然,在交叉编译等时,这会变得更加复杂,但我假设您的构建和目标架构是相同的。
否则是的,你运气不好。
答案 2 :(得分:5)
你运气不好 - 预处理器甚至不知道结构是什么,更不用说任何方法来计算它的大小了。
在这种情况下你可以#define一个常量,你知道结构的大小是什么,然后静态断言它实际上等于使用负大小数组技巧的大小。
此外,您可以尝试执行if (sizeof(Entry) == 12)
,并查看您的编译器是否能够在编译时评估分支条件并删除死代码。这不是一个大问题。
答案 3 :(得分:1)
这可能没有帮助,但如果您能够在C ++中执行此操作,则可以使用模板使编译器在编译时调度到适当的循环:
template <std::size_t SizeOfEntry>
void process_entry_loop(...)
{
// ... the nonoptimized version of the loop
}
template <>
void process_entry_loop<12>(...)
{
// ... the optimized version of the loop
}
// ...
process_entry_loop<sizeof(Entry)>(...);
答案 4 :(得分:1)
另外还有两种方法 - 要么编写一个小应用程序来编写展开的循环,要么在Duff's device上使用具有预期结构大小的变体。
答案 5 :(得分:-1)
如果您想要结构的最小可能大小(或将其与4字节边界或其他任何对齐),您可以使用打包或对齐的属性。
在Visual C ++中,您可以使用#pragma pack,在GCC中可以使用__attribute __((packed))和__attribute __((aligned(num-bytes))。