我有以下foo.c
文件片段:
unsigned char foo[] = {1, 2, 3, 4};
void copy_foo(unsigned char *dest)
{
memcpy(dest, foo, sizeof(foo));
}
我想在另一个C文件(main.c
)中声明一个bar
数组,其大小与foo
相同,以保存copy_foo
的输出:
int main(void)
{
unsigned char bar[?];
copy_foo(bar);
return 0;
}
是否有可能在编译时从main.c
访问sizeof(foo)
,以便它可以用来声明bar
数组?
通常的"解决方案"解决这个问题的方法是在运行时使用某种堆分配来分配内存,但我正在寻找一个静态的,编译时的解决方案,因为一些嵌入式系统禁止使用动态分配。
当然,我可以将#define FOO_SIZE 4
添加到foo.h
,但是如果foo
更改了FOO_SIZE
,则必须手动更改。
这可能吗?
这是我找到的解决方案,供任何感兴趣的人使用。如果有人有更好的解决方案,我仍然有兴趣看看:)
main.c
:
#include "foo.h"
int main(void)
{
unsigned char bar[FOO_SIZE];
copy_foo(bar);
return FOO_SIZE;
}
foo.h
:
#define FOO (unsigned char []){1, 2, 3, 4}
#define FOO_SIZE sizeof(FOO)
void copy_foo(unsigned char *dest);
foo.c
:
#include <string.h>
#include "foo.h"
unsigned char foo[] = FOO;
void copy_foo(unsigned char *dest)
{
memcpy(dest, foo, FOO_SIZE);
}
这要归功于"复合字面量",它允许我们定义"匿名";数组。FOO
被定义为这些复合字面值之一,它可以用来初始化foo
数组。有趣的是,它也可以在sizeof
中使用,下面这行:
unsigned char bar[FOO_SIZE];
评估:
unsigned char bar[sizeof((unsigned char []){1, 2, 3, 4})];
是完全合法的
现在要证明在编译时的结果确实是4,并且它不会将数组的额外副本添加到数据部分:
我用:
编译gcc main.c foo.c -S
Infoo.s
:
.globl foo
.data
.type foo, @object
.size foo, 4
foo:
.ascii "