我有这段代码
struct counter_info {
atomic_t counter;
char *name;
} __attribute__((packed));
extern struct counter_info __start_counters;
extern struct counter_info __stop_counters;
#define __DOSOMETHING(F) \
do{ \
static struct counter_info __counter_info_##F \
__attribute((__section__("counters"))) \
__attribute((__used__)) = { \
.name = #F, \
}; \
atomic_set(&__counter_info_##F.counter, 0); \
\
}while(0)
我将此宏称为:
__DOSOMETHING(FOO)
我想从其他代码访问__counter_info_##F
#define __DOSOMETHINGELSE(F) \
do{ \
atomic_inc(&__counter_info_##F.counter); \
}while(0)
__DOSOMETHINGELSE(FOO)
但是我从编译器得到一个未声明的错误。这是为什么?可以吗?
编辑:
确切的错误是
error: ‘__counter_info_FOO’ undeclared (first use in this function)
note: in expansion of macro ‘__DOSOMETHINGELSE’
答案 0 :(得分:4)
你无法从另一段代码中获取该结构,因为你已经在一个支撑块内声明了它。 C范围规则禁止访问该块之外的代码。即使您让宏生成正确的名称,这也是正确的:__counter_info_F而不是__counter_info_FOO。
顺便说一句,这不是一个#define问题。当C看到代码时,所有宏处理都完成,编译器只看到预处理器生成的标记。
找到一种在没有宏的情况下完成工作的方法......然后找出一个宏表示来简化编码。
一种方法是使用不使用do循环来封闭这些变量的宏。现在的问题是生成唯一的名称。仔细查看这些宏,您会发现创建一次性循环以解决问题......创建双重定义的重复名称。如果打开宏生成的代码,则必须以另一种方式解决重复的名称问题......可能是通过添加宏参数。
有一件事,为了记录:你不需要像do或for包含普通块的复合语句。只是用括号括起来就足够了。你可以脱掉"做"在开头和"而(0);"最后,得到同样的效果。
答案 1 :(得分:0)
如果结构在函数中声明为static,则其可见性将仅限于该函数。示例(没有宏):
struct hoppa {
int i;
};
void start(void)
{
static struct hoppa one = {1};
}
void use_it(void)
{
one.i = 2; //FAIL
}