I want to use a basic macro in C to access a certain Bit b in a char-Array (*char) Arr:
#define TstBit (Arr,b) ( Arr[b/8] & (1 << (b%8)) )
however upon usage like such:
int foo(const char *charArray) {
int readindex = 0;
[...]
if(TstBit(charArray,readIndex++)) {
I get an error on the line with the #define-Statement:
main.c | line 7 | error: 'Arr' undeclared (first use in this function)
I'm suspecting I'm either passing the arguments poorly when calling the Function or that the #define needs some more parentheses.
The space after TstBit seems to be the problem here. The pre-processor, unlike the C compiler, is a bit more fussy about spaces.
With your macro, what the pre-processor does is replace all occurrences of TstBit with (Arr,b) which is not your intention.
#define TstBit(Arr,b) ( Arr[b/8] & (1 << (b%8)) )
should work the way you want.
EDIT: Also note that there is a problem with the way you are trying to use this macro, as noted in this comment!
Macro arguments should ideally not have side-effects. If they do, you should take care that they do not lead to undefined or unintended behaviour.
Related
Please give me full description....
The first snippet of code has the 'function call' (macro invocation) before the increment operator, and second one has the function call after the increment operator.
#include <stdio.h>
#define square(x) x*x
int main()
{
int a,b=3;
a=square (b)++;
printf("%d%d",a,b);
return 0;
}
output:
124
why is 124 returned here
#include <stdio.h>
#define square(x) x*x
int main()
{
int a,b=3;
a=square (b++);
printf("%d%d",a,b);
return 0;
}
output:
125
and 125 here?
The thing to keep in mind is that macros provide simple substitution of preprocessor tokens. In particular, they may evaluate their arguments more than once, and if not guarded by parentheses, they may produce unintended reassociation.
In the first example, we have
a=square (b)++;
This expands to:
a=b*b++;
This is actually undefined behavior, since the b and b++ are unsequenced, and b++ modifies b. In your case, you are seeing 12 and 4 for a and b, so it would seem that the first value of b is picking up the incremented value, so you're getting 4*3, but you can't count on this behavior. The final value of b is 4 since it is incremented once.
In the second example, we have:
a=square (b++);
This expands to:
a=b++*b++;
This is again undefined behavior. In your case, it appears that you're getting 4*3 (or 3*4), but again, you can't count on this behavior. The final value of b is 5 since it is incremented twice, but this too is undefined behavior.
In addition to Tom's answer, which explains what is happening, here is an example of how you could define a macro for squaring a number safely:
#define SQR(x) ( \
{ \
__auto_type x_ = (x); \
\
x_ * x_; \
} \
)
It only has an appearance of x, and therefore it doesn't evaluate it twice. The copy x_ is used instead. Note that variables created in a macro may conflict with other variables created in the function that calls the macro. To avoid name collisions you use special names that shouldn't be used in normal code such as a trailing _.
With this macro, this:
a = SQR(b++);
will be equivalent to this:
a = SQR(b);
b++;
Warning: This works on some compilers as an extension (GCC for example), but it is not standard C.
Another option, if you want standard C, is to use an inline function. It is ok if you want it to work on just one type (there is _Generic in C11, but I never used it, so no idea).
i'm trying to define the following macro:
#define UTF8_2B(c) if((0xc0 & c) == 0xc0){return 1;}
But i'm met with the error:
expected expression before ‘if’
The macro is called like so:
int i = UTF8_2B(c);
Where c is an unsigned char read from a file.
Why does this happen? Can you not use if else statements in macros?
Also, I've read that it's not a good idea to use semicolon in your macros, but i didn't understand why.
I'm new to c so the more thorough the answer the better.
C (and C++) preprocessor macros are essentially "copy-paste" with argument substitution. So your code becomes:
int i = if((0xc0 & c) == 0xc0){return 1;}
And this is invalid syntax.
You're assigning the result of your macro to a variable. You cannot do that with the current macro (return returns from the current function, and doesn't return something to be assigned to i: so not what you want).
If you're using gcc, you can view what your pre-processed code looks like with the -E command line.
So you can use if in macros, but not in macros that are used like functions, which are supposed to return a value.
Moreover:
if c is a complex expression, operator precedence could make the macro generate wrong code
the macro should provide a way to require semicolon, so IDEs and human readers see that as a normal function
I'd propose a simple test instead (which yields 1 if true, 0 otherwise), which meets the "need semicolon" standard and is safe to use with a complex c expression:
#define UTF8_2B(c) ((0xc0 & (c)) == 0xc0)
The ternary operator exists for this purpose. Assuming you want 1 if true and 0 if false, the correct macro is:
#define UTF8_2B(c) (((c) & 0xC0) == 0xC0 ? 1 : 0)
Now you can assign the result. Using return in a macro will return from the enclosing function, not from the macro, and is almost always a bad idea.
I have read lots on stringizing macros, but I obviously don't quite understand. I wish to make a string where the argument to the macro needs to be evaluated first. Can someone please explain where I am going wrong, or perhaps how to do this better?
#define SDDISK 2 // Note defined in a library file elsewhere ie not a constant I know)
#define DRIVE_STR(d) #d ":/"
#define xDRIVE_STR(x) DRIVE_STR(x)
#define FILEPATH(f) xDRIVE_STR(SDDISK + '0') #f
const char file[] = FILEPATH(test.log);
void main(void)
{
DebugPrint(file);
}
The output is: "2 + '0':/test.log",
But I want "2:/test.log"
The C PREprocessor runs before the compiler ever sees the code.
This means that the equation will not be evaluated before it is stringified; instead, the preprocessor will just stringize the whole equation.
In your case just removing the +'0' will solve the problem as the value of SDDISK does not need casting to a char before it is stringified.
However, should you actually need to perform a calculation before stringizing you should either:
Use cpp's constexpr.
Complain to your compiler vendor that a constant expression was not optimized.
Use a preprocessor library to gain the wanted behaviour.
When I run the following code,
#include<stdio.h>
#define X (4+Y)
#define Y (X+3)
int main()
{
printf("%d",4*X+2);
return 0;
}
I am getting the following output:
Error: Undefined symbol 'X'
Can someone please explain the output?
It is because the macro expects and argument since its defined with parentheses.
You would need to define it as
#define X 4+Y and #define Y X+3. Then you would run into another trouble because of cyclic definition in macros.
To be even more correct, as Drew suggested; when the example would be compilable when defining macros one usually puts the parentheses around expression to ensure expected operator precedence.
So your best shot would be:
#define X (4+Y)
#define Y (X+3)
Very close to your initial example, just a space character between name of a macro and its definition. However, it is still impossible to properly expand the macro due to the cyclic reference.
How to check what happened:
You can use gcc -E, which outputs a pre-processed file. It generates lots of output so I used tail. I also used 2>err to redirect error stream to a file, so the output is clear.
luk32:~/projects/tests$ gcc -E ./cyclic_macro_with_no_spaces.c 2> err | tail -n 6
int main()
{
printf("%d",4*X+2);
return 0;
}
luk32:~/projects/tests$ gcc -E ./cyclic_macro.c 2> err | tail -n 6
int main()
{
printf("%d",4*(4+(X+3))+2);
return 0;
}
In 1st example the X did not expand at all. While in the latter both macros got expanded, although only one. Giving the same output that Geoffrey presented in his answer.
Whether no space is a typo or not there is an undefined symbol 'X'. For different reason that are possible to trace by analyzing err files.
If the macros are left as invalid function-like macros, they are not getting expanded at all because you did not call it with parentheses. So X is never replaced with anything by the pre-processor, and is the reason for the Undefined symbol 'X' in your sample code.
If you wanted this to be expanded you would have to call it with parentheses like this:
printf("%d",4*X()+2);
This though would just error out when pre-processed as 4+Y and X+3 are not valid macro parameter names.
If your answer is corrected somewhat so that those defines are proper defines, and not function-like macros, ie:
#define X (4+Y)
#define Y (X+3)
You have a circular reference between the defines...
X -> Y -> X... etc.
Since it will only expand the macro once, it is getting expanded to
printf("%d",4*(4+(X+3))+2);
This explains why X is the undefined symbol in this use case.
You miss spaces
#define X (4+Y)
#define Y (X+3)
KdPrint(("Enter HelloWDMAddDevice\n"));
What's the reason for doing that?
That is so you can pass an entire argument list to the macro and have it pass it on to a function that takes a variable number of arguments.
I would bet anything that the definition of that macro is:
#if DEBUG /* or something like it */
#define KdPrint(args) (printf args)
#else
#define KdPrint(args) /* empty */
#endif
Or similar to some other function that works just like printf.
If it were defined as printf(args), then you could only pass the single string argument, because an argument to a macro can't contain a comma that isn't inside a nested parenthesis.
It causes everything inside the parens to be treated as a single parameter to the macro. In the example shown, it can allow for varargs types of parameters:
KdPrint(( "My info is %s\n", "my name" ));
As well as
KdPrint(( "fn %s ln %s\n", "my", "name" ));
If the macro in question was not well written using parentheses, it might be necessary because of operator precedence. Take this macro for example:
#define MY_MACRO(a) a * 11
Well, if you did this:
int b = MY_MACRO(1 + 2);
b, instead of being 33 like it should, would actually be replaced with int b = 1 + 2 * 11 which is 23 and not 33. If your macro isn't written like that, though (without parenthesis around the a) then it's unnecessary.
If this is the KdPrint() that you are talking about, then this is because you can use KdPrint() macro with format arguments, and it is not a variable length macro.
For example, you can do:
KdPrint(("The answer is %d\n", 42));
and so on.
For your specific example, I cannot tell you, because I don't know what is XdPrint.
But in a more general case, it is because a macro I just like a search and replace. Suppose you have:
#define MULT(a,b) (a*b)
If you call MULT(1+1, 2+2), it would become 1+1*2+2, and result as 5 instead of 8 as you would expect. Doing MULT((1+1), (2+2)) would gives you the expected result. That is why you need to double the brackets.