Creating a macro with ## operator - c

Sorry I may be repeating a question asked previously, but I did not get the answer I am looking for.
So Here is what I am trying to create:
typedef struct flags
{
unsigned char flag0:1;
unsigned char flag1:1;
unsigned char flag2:1;
unsigned char flag3:1;
unsigned char flag4:1;
unsigned char flag5:1;
unsigned char flag6:1;
unsigned char flag7:1;
}BFLAG;
typedef union
{
unsigned char byte;
BFLAG bitflg;
}GENFLAG;
GENFLAG status_flag, hmi_flag;
Then I want to create macros to address specific bits as follows:
#define EDIT_PARAM status_flag.bitflg.flag0 // l: Locked for editing, 0:Editable
#define HIDE_PARAM status_flag.bitflg.flag1 // 1: parameter is hidden, 0:visible
#define LOCK_PARAM hmi_flag.bitflg.flag0 // 1: Password Unlock, 0: locked 1.
etc.
So I want to be able to concatenate a common string such as "status_flag.bitflg.flag" using the ## operator with 0, 1, 2, 3 etc in each instance creating a new macro. But I want to use macros such as
EDIT_INDEX for 0, HIDE_INDEX for 1 etc.
#define EDIT_INDEX 0
#define HIDE_INDEX 1
However if I use this directly in a macro such as
#define CONCAT(x, y) x##y
#define EDIT_PARAM CONCAT(status_flag.bitflg.flag, EDIT_INDEX)
All I get is the concatenation of the string on the left hand side with EDIT_INDEX as a string not the expanded macro as
status_flag.bitflg.flag0
What should I do if I want it to create the expansion as shown above?
Any and all help will be sincerely appreciated. Sorry if my problem statement is found wanting.
I tried the following
#define CONCAT(x, y) x##y
#define EDIT_PARAM CONCAT(#status_flag.bitflg.flag, EDIT_INDEX)
It gives the output as "status_flag.bitflg.flagEDIT_INDEX", not "status_flag.bitflg.flag0" as intended.

This is a known limitation of macro expansion in C.
It's generally worked around by using:
#define CONCAT1(x, y) x##y
#define CONCAT(x, y) CONCAT1(x, y)
Instead of just
#define CONCAT(x, y) x##y
Explanation:
The combination of CONCAT() and CONCAT1() makes the preprocessor evaluate x and y before concatenating them.

Related

Macros #if directive with non integer definition

I'm having a 20yo legacy code (pure C) which defines:
#define X float
before first function and before another function:
#undefine X
#define X double
I'm writing a code which is supposed to work with both definitions (and it'll be copied into both functions automatically). But it's impossible to make such code in a few cases. For these cases I need to detect if my X is float or double and use #if #else #endif.
The #if (X == float) is resolved as 0 == 0 and won't work.
In theory I can grab into legacy code and modify these definition to make my life easier, but I wonder if there is any macro magic which would allow me to workaround this without touching the legacy? Something with conversion X to string may be? Any ideas?
Concatenate with prefix that expands to something you can control.
#define PREFIX_float 0
#define PREFIX_double 1
#define CONCAT(a, b) a##b
#define XCONCAT(a, b) CONCAT(a, b)
#if XCONCAT(PREFIX_, X) == PREFIX_float

using #define and # for stringizing to convert another macro constant to string

With reference to this question Quote macro for defining string, Idea is that I want to print the value of a macro constant, say for the following code:
#include<stdio.h>
#define X 4
#define Tostring(x) #x
main()
{
printf(Tostring(X));
}
It is printng X instead of 4, but with Quote macro for defining string I know how to correct it, but can someone explain what exactly is gong on here?
To print 4 as you wish you can one of these:
Stringizing the result:
#include<stdio.h>
#define Tostring(x) str(x)
#define str(x) #x
#define X 4
int main()
{
printf(Tostring(X));
}
or using function like macros to convert X to int:
#include<stdio.h>
#define X 4
#define Tostring(x)(X)
int main()
{
printf("%d\n", Tostring(X));
}
The first example is one of the examples that is given in documentation. There it is stated that two levels of macros shall be used if you want to stringize the result of the expansion of a macro. The result of the expansion is the following:
Tostring (X)
-> Tostring(4)
-> str (4)
-> "4"
In the second example you are relating the argument of Tostring macro with the X from the #define X 4 and thus you can print the value as an int.

Preprocessors in C [duplicate]

This question already has answers here:
C macros and use of arguments in parentheses
(2 answers)
Closed 3 years ago.
I have a doubt in the output of a code. The code uses preprocessors of c language. The code is given below,
#include <stdio.h>
#define sqr(x) x*x
int main() {
int x = 16/sqr(4);
printf("%d", x);
}
The result of sqr(4) is equal to 16. So, the value in x must be 1 (16/16=1). But if I print the value of x, the output is 16. Please explain me why this is happening.
I am attaching the screenshot of output pane.
Output Window
In C, macros are filled into your code upon compilation. Let's consider what happens in your case:
Your macro is:
#define sqr(x) x*x
When it gets filled into this:
int x = 16/sqr(4);
You would get:
int x = 16/4*4;
Operator precedence being equal for / and *, this gets evaluated as (16/4)*4 = 16, that is, from left to right.
However, if your macro were this:
#define sqr(x) (x*x)
then you would get:
int x = 16/(4*4);
... and that reduces to 1.
However, when the argument for your macro is more complex than a simple number, e.g. 2+3, it would still go wrong. A better macro is:
#define sqr(x) ((x)*(x))
After macro replaces your expression, it becomes int x = 16/4*4 and is evaluated accordingly. i.e. (16/4)*4 which is 16.
sqr(x) doesn't calculate 4*4, it is not a function.
You are actually doing 16/4*4 which is in fact 16.
You can change your define to
#define sqr(x) (x*x)
Now you will be doing 16/(4*4).
It is expanded to
int x = 16/4*4;
Something like
#define sqr(x) ((x) * (x))
would be more safe, precedence and associativity-wise, still works poorly in expressions like sqr(a++). Inline functions are simpler to use in this context.

How to control C Macro Precedence

#define VAL1CHK 20
#define NUM 1
#define JOIN(A,B,C) A##B##C
int x = JOIN(VAL,NUM,CHK);
With above code my expectation was
int x = 20;
But i get compilation error as macro expands to
int x = VALNUMCHK; // Which is undefined
How to make it so that NUM is replaced first and the JOIN is used?
You can redirect the JOIN operation to another macro, which then does the actual pasting, in order to enforce expansion of its arguments:
#define VAL1CHK 20
#define NUM 1
#define JOIN1(A, B, C) A##B##C
#define JOIN(A, B, C) JOIN1(A, B, C)
int x = JOIN(VAL,NUM,CHK);
This technique is often used with the pasting and stringification operators in macros.

Errors initializing array in C

I tried to run this code:
#define ROW_CNT 8;
#define COLUMN_CNT 24;
#define FIRST_COLUMN 2;
unsigned int volume[ROW_CNT][COLUMN_CNT][ROW_CNT];
but I get the following errors:
expected identifier or '(' before ']' token
Why is that?
Take off the semicolons on your #defines.
The #define directives are handled by the preprocessing stage of compilation, which is all about text substitution. So, whenever the preprocessor performs text substitution, your program becomes
unsigned int volume[8;][24;][2;];
which isn't valid C.
#define ROW_CNT 8;
#define COLUMN_CNT 24;
#define FIRST_COLUMN 2;
should be
#define ROW_CNT 8
#define COLUMN_CNT 24
#define FIRST_COLUMN 2
semicolons should not be used for #define
A pre-processor definition, such as ROW_CNT, replaces any instances of the identifier in your code with the value it's defined as being. Therefore once the pre-processor has expanded your macros, your code will look like:
unsigned int volume[8;][24;][2;];
As you can see, the semicolon is included after 8, 24 and 2, since that's how you defined ROW_CNT, COLUMN_COUNT and FIRST_COUNT to be, and that's obviously not valid C syntax.
Remove the semicolons from the end of your #defines and the code will compile.

Resources