我正在研究硬件编程。我创建了以下Varidic宏。
#define UPDATE_DATA(bit,...) { \
do { \
int i; \
int j = 0; \
int _args[] = {__VA_ARGS__};\
int *addr = (int *) ADDR ; \
for (i = 0; i < (sizeof(_args)/sizeof(_args[0])); i++) {\
*(int *) (DATA_ADDR - j) |= _args[i];\
j = j + 0x4; \
}\
*addr |= 1 << bit;\
}while (0); \
}
如果我使用像UPDATE_DATA(1,2,3);
那样它的工作但是如果在循环中使用这个宏,就像
msg_id = MSG_1;
for(j=0; j<15 ; j++)
{
msg_id = msg_id +1;
l_data = data_array[j];
UPDATE_DATA(msg_id,l_data,(SYSTEM_BASE_ADDR6+offset));
offset = (offset + 0x4);
}
我到了
Error: #28: expression must have a constant value
LOGGER_UPDATE_DATA(msg_id,l_data,(SRAM0_SYSTEM_BASE_ADDR6+offset));
我没有得到我在这里做错了什么!!
答案 0 :(得分:1)
我的建议是不使用可变参数宏。它们扩展了代码大小并使维护变得困难。
假设您不需要将-1作为值传递,则可以使用stdarg.h
#include <stdio.h> // for test output, not actually needed when you do the I/O
#include <stdarg.h>
#define LOGGER ((volatile int *)0x1234)
#define LOGGER_DATA ((volatile int *)0x5678)
void sendToLoggerV(int bit, va_list ap)
{
int i, value;
for (i = 0; ; ++i)
{
// do your write here...
value = va_arg(ap, int);
if (value == -1)
break;
// Can't really write it in this test, but this is what you would do:
//LOGGER_DATA[-i] = value;
printf("Pretending to write %d to %p\n", value, (void*)&LOGGER_DATA[-i]);
}
//*LOGGER |= 1 << bit;
printf("Pretending to OR %d to %p\n", 1<<bit, (void*)LOGGER);
}
void sendToLogger(int bit, ...)
{
va_list ap;
va_start(ap,bit);
sendToLoggerV(bit, ap);
va_end(ap);
}
#define SEND_TO(bit, ...) sendToLogger(bit, __VA_ARGS__, -1)
int main()
{
SEND_TO(1, 16, 17, 18, 19);
SEND_TO(2, 30, 31);
}
由于这将在嵌入式系统中运行,我的测试用例只是打印消息来说出它会做什么。注释掉的行将执行实际的内存写入。我已经为你的内存映射I / O地址使用了人为的地址(0x1234和0x5678)。
此代码输出以下内容,符合您的规格:
Pretending to write 16 to 0x5678
Pretending to write 17 to 0x5674
Pretending to write 18 to 0x5670
Pretending to write 19 to 0x566c
Pretending to OR 2 to 0x1234
Pretending to write 30 to 0x5678
Pretending to write 31 to 0x5674
Pretending to OR 4 to 0x1234