I have the following macros
#define REG_PWR_CTRL 0x2D
#define REG_FIFO_CTL 0x38
#define VERBOSE(...) \
if(verbose) \
printf(__VA_ARGS__);
#define READ_REGISTER(i2c_dev_file, REGISTER, variable) \
{ \
variable = i2c_smbus_read_byte_data(i2c_dev_file, REGISTER); \
}
#define WRITE_REGISTER_VERBOSE(i2c_dev_file, REGISTER, value) \
{ \
short int var = 0; \
i2c_smbus_write_byte_data(i2c_dev_file, REGISTER, value); \
usleep(100); \
READ_REGISTER(i2c_dev_file, REGISTER, var); \
VERBOSE(#REGISTER " :0x%02X\n", var); \
}
I would like the REGISTER
field to not be expanded in the following line
VERBOSE(#REGISTER " :0x%02X\\n", var); \\
For example, When I write
WRITE_REGISTER_VERBOSE(i2c_dev_fd, REG_PWR_CTRL, 0x1A);
WRITE_REGISTER_VERBOSE(i2c_dev_fd, REG_FIFO_CTL, 0xC6);
I get the output
0x2D :0x1A
0x38 :0xC6
I would like to obtain
REG_PWR_CTRL :0x1A
REG_FIFO_CTL :0xC6
I came across a lot of posts that spoke about adding an extra level of indirection.
I tried the answer described here https://stackoverflow.com/a/2653351/1761555 ..although I believe that that answer is for a different problem altogether..
What I did was
#define STRINGIFY(label) (#label)
#define WRITE_REGISTER_VERBOSE(i2c_dev_file, REGISTER, value) \
{ \
short int var = 0; \
i2c_smbus_write_byte_data(i2c_dev_file, REGISTER, value); \
usleep(100); \
READ_REGISTER(i2c_dev_file, REGISTER, var); \
VERBOSE("%s :0x%02X\n", STRINGIFY(REGISTER), var); \
}
But this still gives me the same output as before
Is there any way to achieve this?
You could make REG_PWR_CTRL
and REG_FIFO_CTL
a value of some enum, like
enum registers_en {
REG__NONE,
REG_PWR_CTRL = 0x2d,
REG_FIFO_CTL = 0x38,
};
Then REG_PWR_CTRL
becomes a real identifier of some enum value, and is not macro-expanded in something else (because an enum
definition is not a macro definition, and is not handled by the cpp
preprocessor ).
So define such an enum, and preprocess your source code (eg with gcc -C -E yoursource.c > yoursource.i
) then look (eg with less yoursource.i
) inside the preprocessed file. All occurrences of REG_PWR_CTRL
will still be there.
Be aware the the preprocessor is conceptually the first phase of a compiler: even in compilers like current GCC 4.8 where the preprocessor is not an external program but implemented thru a libcpp internal library, the compiler works by first preprocessing the source code and obtaining a stream of lexemes , and then occurrences of REG_PWR_CTRL
stay as lexemes (not as literal constants 0x2d
as when you #define REG_PWR_CTRL 0x2d
...).
You need to read more about the preprocessor cpp , and take the habit to look into the preprocessed form.
Another advantage of enum
-s is that if you compile with debugging info (eg gcc -g
) the debugging info hence the debugger gdb
knows about enum
.
I modified your code for simplicity:
#include <stdio.h>
#define REG_PWR_CTRL (0x2D)
#define GET_VAR_NAME(var) (#var)
#define VERBOSE(...) (printf(__VA_ARGS__))
#define ANOTHER_LAYER(arg) ( \
VERBOSE("%s = %#X; %s = %#X\n", \
GET_VAR_NAME(REG_PWR_CTRL), REG_PWR_CTRL, \
GET_VAR_NAME(arg), arg) \
) \
int main(void)
{
int num = 5;
VERBOSE("%s = %#X\n", GET_VAR_NAME(REG_PWR_CTRL), REG_PWR_CTRL);
ANOTHER_LAYER(num);
return 0;
}
Output:
REG_PWR_CTRL = 0X2D
REG_PWR_CTRL = 0X2D; num = 0X5
Use macros for simple things.
This is because:
So just use functions for complex stuff. Use macros for simple stuff
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.