This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Unintended multiple evaluation of parameter in macro
(1 answer)
Closed 6 years ago.
#include <stdio.h>
// 2.1
#define subm(a,b) (a - b)
#define cubem(a) (a * a * a)
#define minm minf
#define oddm oddf
//---------------------------Given Code------------------------------------
int subf(int a, int b) {
return a - b;
}
int cubef(int a) {
return a * a * a;
}
int minf(int a, int b) {
if (a <= b) {
return a;
} else {
return b;
}
}
int oddf(int a) {
if (a % 2 == 0) {
return 0;
} else {
return 1;
}
}
//----------------------------Given Code----------------------------------
// 2.2
int main() {
int a = 5;
int b = 7;
subf(a,b);printf("subf = %d\n", subf(a,b));
subm(a,b);printf("subm = %d\n", subm(a,b));
subf(a++,b--);printf("subf = %d\n", subf(a++,b--));
subm(a++,b--);printf("subm = %d\n", subm(a++,b--));
cubef(a);printf("cubef = %d\n", cubef(a));
cubem(a);printf("cubem = %d\n", cubem(a));
cubef(--a);printf("cubef = %d\n", cubef(--a));
cubem(--a);printf("cubem = %d\n", cubem(--a));
minf(a,b);printf("minf = %d\n", minf(a,b));
minm(a,b);printf("minm = %d\n", minm(a,b));
minf(--a,--b);printf("minf = %d\n", minf(--a,--b));
minm(--a,--b);printf("minm = %d\n", minm(--a,--b));
oddf(a);printf("oddf = %d\n", oddf(a));
oddm(a);printf("oddm = %d\n", oddm(a));
oddf(a++);printf("oddf = %d\n", oddf(a++));
oddm(a++);printf("oddm = %d\n", oddm(a++));
}
I'm having some trouble with putting the functions inside the macro. My professor wants us to understand how macro and functions are processed. The way I'm doing it is basically as you see here, but it's not working correctly, or at least
#define cubem(a) (a * a * a)
Is generating an error and I don't know why. Can someone please help?
edit: the error is as shown
hw02q2.c:42:31: warning: multiple unsequenced modifications to 'a'
[-Wunsequenced]
printf("cubem = %d\n", cubem(--a));
^~
hw02q2.c:4:19: note: expanded from macro 'cubem'
#define cubem(a) (a * a * a)
The reason is that
#define cubem(a) (a * a * a)
/* and later using it .... */
printf("cubem = %d\n", cubem(--a));
does text substitution, and produces
printf("cubem = %d\n", (--a * --a * --a));
which modifies a three times in one statement. That is undefined behaviour according to the C standard.
In comparison,
int cubef(int a) {
return a * a * a;
}
/* and later */
printf("cubef = %d\n", cubef(--a));
evaluates --a once, passes the resultant value to cubef().
If you really want to "put a function in a macro", then do something like
#define cubem(a) cubef(a)
which causes the statement
printf("cubem = %d\n", cubem(--a));
to become
printf("cubem = %d\n", cubef(--a));
The problem with this is that it does not work with a macro that uses its argument more than once. For example
int sq(int a) {return a * a;}
#define cubesq(a) (a * sq(a)) /* uses a more than once
causes
printf("cubesq = %d\n", cubesq(--a));
to be seen by the compiler as
printf("cubem = %d\n", (--a * cubesq(--a));
which, again, modifies a more once and causes undefined behaviour.
The reason is simple: the preprocessor does TEXT SUBSTITUTION and modifies source code seen by a later phase of the compiler.
Instead of "trying to put a function inside a macro", simply don't use macros. Write functions. Use functions. Or use macros, but respect their limitations (i.e. they don't work like functions do, even if they look like functions).
C Macros perform textual substitution: each instance is replaced with the macro definition with the macro parameter names replaced with the exact text of the instance arguments.
Your cubem macro defined as #define cubem(a) (a * a * a) will expand this way:
cubem(--a) -> (--a * --a * --a)
Modifying a multiple times within the same expression has undefined behavior. You cannot work around this problem portably. You could try using compiler extensions if you are familiar enough and don't mind relying on non-portable constructions.
The correct way to implement the function and have it expand inline is via an inline function definition:
static inline cubem(int a) { return a * a * a; }
Note also that the macro has other problems:
cubem(1 + 1) expands to (1 + 1 * 1 + 1 * 1 + 1) which evaluates to 4 instead of 8.
To avoid this problem, all macro arguments should be parenthesized:
#define cubem(a) ((a) * (a) * (a))
But this definition still does not support arguments with side effects:
cubem(getchar()) will read 3 bytes from standard input.
Since you invoke cubem(--a) like this, your cubem definition should avoid side effect.
#define cubem(a) \
({ \
typeof(a) dummy_a = (a); \
dummy_a * dummy_a * dummy_a; \
})
Above is a gcc c extension, read the gcc document, chapter
Statements and Declarations in Expressions
Related
I was just going through certain code which are frequently asked in interviews. I came up with certain questions, if anyone can help me regarding this?
I am totally confused on this now,
#include <stdio.h>
#include <conio.h>
#define square(x) x*x
main()
{
int i, j;
i = 4/square(4);
j = 64/square(4);
printf("\n %d", i);
printf("\n %d", j);
printf("\n %d", square(4));
getch();
}
The output is:
4
64
16
I am wondering, why did square(4) return 1 when I divided it? I mean, how can I get the value 4 and 64 when I divide it, but when used directly I get 16!!?
square is under-parenthesized: it expands textually, so
#define square(x) x*x
...
i=4/square(4);
means
i=4/4*4;
which groups as (4/4) * 4. To fix, add parentheses:
#define square(x) ((x)*(x))
Still a very iffy #define as it evaluates x twice, so square(somefun()) calls the function twice and does not therefore necessarily compute a square but rather the product of the two successive calls, of course;-).
When you write i=4/square(4), the preprocessor expands that to i = 4 / 4 * 4.
Because C groups operations from left to right, the compiler interprets that as i = (4 / 4) * 4, which is equivalent to 1 * 4.
You need to add parentheses, like this:
#define square(x) ((x)*(x))
This way, i=4/square(4) turns into i = 4 / ((4) * (4)).
You need the additional parentheses around x in case you write square(1 + 1), which would otherwise turn into 1 + 1 * 1 + 1, which is evaluated as 1 + (1 * 1) + 1, or 3.
i=4/square(4);
expands to
i=4/4*4;
which equivalent to
i=(4/4)*4;
Operator precedence is hurting you.
The macro is expanded by the pre-processor such that
i=4/4*4;
j=64/4*4;
which is equivalent to:
i=(4/4)*4;
j=(64/4)*4;
That's because the compiler replaces it with:
i=4/4*4;
j=64/4*4;
i = (4/4)*4 = 1*4 = 4.
j = (64/4)*4 = 16*4 = 64.
j = 4/square(4) == 4/4*4 == 1*4 == 4
Manually expand the macro in the code, and it will be clear. That is, replace all the square(x) with exactly x*x, in particular don't add any parentheses.
define is just a text macro
main()
{
int i,j;
i=4/ 4 * 4; // 1 * 4
j=64/4 * 4; // 16 * 4
printf("\n %d",i);
printf("\n %d",j);
printf("\n %d",square(4));
getch();
}
It's a macro! So it returns exactly what it substitutes.
i = 4/4*4; Which is 4...
j = 64/4*4; Which is 16...
Try this for your macro:
#define square(x) ((x)*(x))
Because of operator precedence in the expression after the preprocessor - you'll need to write
#define square(x) (x*x)
As the other answers say, you're getting burned by operator precedence. Change your square macro to this:
#define square(x) (x*x)
and it'll work the way you expect.
I have two C functions f1 and f2 that take the same arguments. Based on a condition, I need to invoke one or the other one with the same arguments:
if (condition) {
result = f1(a, b, c);
} else {
result = f2(a, b, c);
}
I understand it is possible to use the syntax:
result = condition ? f1(a, b, c) : f2(a, b, c)
Is it be possible to have a DRY syntax that requires to write arguments a single time?
Yes, it works fine just like you suggested.
The function call operator () just needs a left-hand-side that evaluates to a function pointer, which names of functions do.
There's no need to derefence function pointers when calling, the () operator does that.
This sample program demonstrates:
#include <stdio.h>
static int foo(int x) {
return x + 1;
}
static int bar(int x) {
return x - 1;
}
int main(void) {
for (int i = 0; i < 10; ++i)
printf("%d -> %d\n", i, (i & 1 ? foo : bar)(i));
return 0;
}
It prints:
0 -> -1
1 -> 2
2 -> 1
3 -> 4
4 -> 3
5 -> 6
6 -> 5
7 -> 8
8 -> 7
9 -> 10
There is nothing strange here.
And since C predates Python by a fair bit, perhaps it's Python's semantics that are C-ish here. Or just plain sane, of course. :)
It is possible to use a function pointer like this:
int (*f)(int, int, int, ...);
f = condition ? f1 : f2;
result = (*f)(a, b, c, ...);
Consider the following code i managed to write:
#include <stdio.h>
#define FOR(A, B, C) for(A; B; C++)
int main()
{
FOR(i=0, i<10, i)
printf("%i", i);
return 1;
}
The output is:
0123456789
If i do FOR(i=5, i<10, i)
then respectively the output is 56789
My questions are is that legal? Will it cause any errors in different cases? Does it works exactly like a for loop?
Yes it's a "legal" macro, but no, it does not work like a real for loop.
Your macro won't handle this:
int a, b;
for(a = 0, b = 4711; a < b; ++a);
for instance, since you can't distinguish the , used to build a longer initializing expression to the one used to separate the expressions that make up the parts:
FOR(a = 0, b = 0, a < b, ++a);
will break, since it looks like a call with 4 arguments instead of 3.
A macro is just copied everywhere the preprocessor sees you using the macro keyword. It just copies the text, nothing more.
To elaborate on that a bit more, consider this example:
#define MY_MACRO a
int MY_MACRO = 5;
When the preprocessor comes along it will take the above and change it to:
int a = 5;
and then the compiler will come along and compile it like normal C/C++ code.
When you add arguments to your macro, they are just substituted in place within your macro. This can be a problem, consider the following two macros:
#define BAD_MACRO(a, b) a*b
#define GOOD_MACRO(a, b) (a)*(b)
They look almost the same, but consider the following:
int k = BAD_MACRO(2, 3); // k = 2*3 = 6
int j = GOOD_MACRO(2, 3); // j = 2*3 = 6
int m = BAD_MACRO(2+1, 3); // m = 2+1*3 = 5
int n = GOOD_MACRO(2+1, 3); // n = (2+1)*3 = 9
Although note that neither of these macros are good or bad, they just don't have the same behaviour as a typical function.
Here I know that the following code simply copies the character i rather than its value to the preprocessor statement (which makes a error for undefined symbol i in compile-time).
What I want is:
Is their a way such that the compiler treats, i as a variable with some value rather than a character ?
#include <stdio.h>
#define PRINT(x) printf("%d \n", y ## x)
int main(void) {
int y1=0 , y2=1 , y3=4;
for(int i=1; i <= 3; ++i) {
PRINT(i);
}
return 1;
}
About the pre-processor
First of all, I think there's a need to clarify how the preprocessor works: it pre-processes the input files, which means it runs before the compiler. Unfortunatly, for historical reasons, it doesn't know anything about C or C++, doesn't parse anything, and just does very simple textual operations on words and parenthesis. Just to illustrate my point:
#define this __FILE__
#define file -- Hell no!
#define fine(a, b) fine: a ## _ ## b
Ok, so this is not a valid C or C++ file
But the preprocessor will run just fine(go, try!)
Run this with a pre-processor, for example gcc -x c -E -P test.txt and you'll get:
Ok, so "test.txt" is not a valid C or C++ -- Hell no!
But the preprocessor will run just fine: go_try!
So, obviously, when the preprocessor sees PRINT(i) in your code, it replaces it with printf("%d \n", yi) without thinking much about it. And it has absolutely no idea i is a variable, don't even think about evaluating it's value.
Solutions
Basically, what you want is print a bunch of numbers.
You could simply do
printf("0\n1\n4\n");
But this lacks makes changing numbers cumbersome,
so let's go with
printf("%d\n%d\n%d\n", 0, 1, 4);
Which makes it easy to change a number, but not to add/remove one.
Ok so how about:
printf("%d\n", 0);
printf("%d\n", 1);
printf("%d\n", 4);
Yeah, you can change/add/remove numbers easily but as any sane programmer you hate repetition. So, we need some kind of loop.
By far the simplest and most straightforward way to iterate in C is at runtime, using an array:
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/sizeof(int); ++i) {
printf("%d\n", y[i]);
}
If you want, you can hide the printf using a function:
inline void print_int(int* y, int i) { print_int(y[i]); }
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/4; ++i) print_int(y, i);
And going further with functions:
inline void print_int(int x) { printf("%d\n", x); }
inline void print_int(int* y, int i) { print_int(y[i]); }
inline void print_ints(int * y, int n)
{
for(int i = 0; i < n; ++i)
print_int(y, i);
}
template<int n> // C++
inline void print_ints(const int[n] & y) { print_ints(&y[0], n); }
int [] y = { 0, 1, 4 };
print_ints(y); // C++
// or in C:
print_ints(y, sizeof(y)/sizeof(int));
Now, what if you absolutely want the generated code to look like solution 3. ? This means you need the iteration to happen at compile-time. Tricky!
That's where the preprocessor can come into play. There are (hacky) ways to make it do this kind of things. I strongly recommend not implementing this yourself (except to play), but use the Boost.preprocessor library instead:
#define PRINTER(R,D, NUMBER) printf("%d\n", NUMBER);
#define NUMBERS (0, 1, 4)
BOOST_PP_LIST_FOR_EACH(PRINTER, _, BOOST_PP_TUPLE_TO_LIST(NUMBERS))
// will expand to printf("%d\n", 0); printf("%d\n", 1); printf("%d\n", 4);
Under standard C, this is not possible; during preprocessing, the compiler simply sees the identifier i as simply that - an identifier. It does not know that i is of type int, or that it's even a variable in the first place.
The easiest way to achieve what's intended is to use an array, like so:
int i;
int y[] = { 0, 1, 4 };
for (i = 0; i < 3; i++) // NOTE: arrays in C start at index 0, not 1
{
printf("%d \n", y[i]);
}
Also note that I got rid of the macro, as you want to use the value of a runtime variable i to select another runtime variable.
This question already has answers here:
C macros and use of arguments in parentheses
(2 answers)
Closed 4 years ago.
I am new to c language. I just wanted to know why is my macro not working properly. It is giving me output as 13 where as my expected output is 24.?
#include<stdio.h>
#define mult(a,b) a*b
int main()
{
int x=4,y=5;
printf("%d",mult(x+2,y-1));
return 0;
}
mult(x+2,y-1) expands to x +2 * y -1 that is equals to 4 + 2 * 5 -1 gives output: 13.
You might be expecting answer (4 + 2) * (5 -1) = 6 * 4 = 24. To make it expand like this you should write parenthesize macro as #H2Co3 also suggesting:
#define mult(a,b) ((a)*(b))
Read aslo: So, what's wrong with using macros? by Bjarne Stroustrup.
This is because C macros are simple textual substitutions, the macro writer must be sure to insert parentheses around every macro variable when it is substituted, and around the macro expansion itself, to prevent the resulting expansion from taking on new meanings.
If you observe your program: mult(a, b) is defined as a * b
mult(x + 2, y - 1) = x + 2 * y - 1 = 4 + 2 * 5 - 1 = 4 + 10 - 1 = 13
The Correct way would be:
mult(a, b) ((a) * (b))
Use parentheses in the macro definition
#include<stdio.h>
#define mult(a,b) ((a)*(b))
int main()
{
int x=4,y=5;
printf("%d",mult(x+2,y-1));
return 0;
}
This is because different arithmetic operators have different precedence levels. Hence always use parentheses while defining the macro.
Because it replaces the arguments literally:
mult(x+2,y-1) --> mult(4+2,5-1) --> 4 + 2*5 - 1 --> 13
Try changing the define to:
#define mult(a,b) (a)*(b)
In this case the result after pre-processing is this:
int main()
{
int x=4,y=5;
printf("%d",(x+2)*(y-1));
return 0;
}
This will solve the problem but it's still not the best way to do it.
#define mult(a,b) ((a)*(b))
This version is considered as good practice because in other types of situation the first one would fail. See the bellow example:
#include<stdio.h>
#define add(a,b) (a)+(b)
int main()
{
int x=4,y=5;
printf("%d",add(x+2,y-1)*add(x+2,y-1));
return 0;
}
In this case it would give an incorrect answer because it is translated by the pre-processor to the fallowing:
int main()
{
int x=4,y=5;
printf("%d",(x+2)+(y-1)*(x+2)+(y-1));
return 0;
}
printing 34 instead of 100.
For the ((a)+(b)) version it would translate to:
int main()
{
int x=4,y=5;
printf("%d",((x+2)+(y-1))*((x+2)+(y-1)));
return 0;
}
giving a correct answer.