C sizeof宏的等价物

ram*_*ion 5 c sizeof c-preprocessor

所以我通过展开一些循环来优化一些代码(是的,我知道我应该依靠我的编译器为我做这个,但我不会选择我的编译器)并且我想这样做有点优雅所以如果我的数据大小由于将来的一些编辑而发生变化,代码将会优雅地降级.

就像是:

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
Run Code Online (Sandbox Code Playgroud)

当然,这不起作用,因为sizeof预处理器无法使用(至少,这个答案似乎表明了这一点).

是否有一个简单的解决方法,我可以使用sizeof一个数据结构与C宏一起使用,或者我只是SOL?

Pav*_*aev 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

sizeof是常量表达式,将常量与常量进行比较也是常量.任何理智的C编译器都会优化掉在编译时始终为false的分支 - 常量折叠是最基本的优化之一.但你输了#warning.


Sea*_*ght 9

如果您使用的是autoconf或其他构建配置系统,则可以在配置时检查数据结构的大小并写出标题(如#define SIZEOF_Entry 12).当然,当交叉编译时,这会变得更复杂,但我假设你的构建和目标架构是相同的.

否则是的,你运气不好.


Ste*_*sop 5

你运气不好 - 预处理器甚至不知道结构是什么,更不用说任何方法来计算它的大小了.

在这种情况下你可以#define一个常量,你知道结构的大小是什么,然后静态断言它实际上等于使用负大小数组技巧的大小.

您也可以尝试一下if (sizeof(Entry) == 12),看看您的编译器是否能够在编译时评估分支条件并删除死代码.这不是一个大问题.