Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I got this problem wrong on a test and am really confused why.
For the given code below, I thought that the output would be 0. Can someone please explain why it isn't?
#include<iostream>
using namespace std;
#define A 0
#define B A+1
#define C 1-B
int main{
cout<<C;
return(0);
}
The correct answer (and real output) is 2.
You will get the correct answer if you expand the macros step by step.
cout<<C;
is
cout<<1-B;
is
cout<<1-A+1;
is
cout<<1-0+1;
which is
cout << 2;
Remember that macros don't work like variables. If you use variables you will get a different answer.
int a = 0;
int b = a+1; // b is 1.
int c = 1-b; // c is 0
cout << c; // Expect 0 in output.
The preprocessor expands macros by doing text substitution, and producing code that is then compiled. The preprocessor (mostly) does not understand expressions - that is handled by a later phase of compilation (after the preprocessor is done).
So C expands to 1-B which expands 1-A+1 which expands to 1-0+1.
This is treated by the compiler as an expression. 1-0+1 gives 2
To get the result (zero) that you expect, you need to use
#define A 0
#define B (A+1)
#define C (1-B)
so C expands to (1-B) which expands (1-(A+1)) which expands to (1-(0+1)), which is evaluated (by the compiler, not the preprocessor) as an expression and gives 0.
Bear in mind that A, B, and C are not variables. They are macros - i.e. directions to the preprocessor on how to do text substitution.
I thought that the output would be 0. Can someone please explain why
it isn't?
Because C expands to 1-B
Now, B expands to A+1.
Now, again, A expands to 0
Filling the gaps:
Since A expanded to 0 then B gets replaced by 0+1
And replacing B in the expression 1-B then becomes 1-0+1
C = 1-B
// ^^^
// A+1
// ^^^
//
// = 1-0+1
Macros are so C89, c++11 came with a better solution to do this at compile time: constexpr.
#include<iostream>
using namespace std;
constexpr auto A = 0;
constexpr auto B = A + 1;
constexpr auto C = 1 - B;
int main{
cout<<C;
return(0);
}
Advantages are: easier to use, as you know the syntax and behavior already. Undefined behavior ain't allowed, which makes this safer. And you can't have circular dependencies giving strange side effects, as it wouldn't compile otherwise.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
As documented here, std::bitset::operator^= returns *this. From that and from the "usual" interpretation of operators such as +=, |=, *= one could reasonably assume that given std::bitset instances (of the same size) a and b, the expression (a^=b).count() will store the result of a bitwise XOR operation in a, and that count() would return the number of bits in a that are set to true. However, as the following minimal example demonstrates, something unexpected happens:
#include <iostream>
#include <bitset>
int main()
{
constexpr unsigned int N=6;
std::bitset<N> a;
std::bitset<N> b;
a.flip();//111111
b[0]=1;
b[4]=1;//b is now 010001 (assuming least significan bit on the right end of the string)
std::cout<<"a=="<<a.to_string()<<std::endl;
std::cout<<"b=="<<b.to_string()<<std::endl;
std::cout<<"(a xor b) to string=="<<(a^=b).to_string()<<std::endl;
//Here is the unexpected part!
std::cout<<"(a xor b) count=="<<(a^=b).count()<<std::endl;
//Note that the following lines would produce the correct result
//a^=b;
//std::cout<<a.count()<<std::endl;
return 0;
}
The output is
a==111111
b==010001
(a xor b) to string==101110
(a xor b) count==6 //this is wrong!!!!! It should be 4...
A quick look at the implementation of std::bitset (see here) seems to indicate that the reference that is returned is indeed a reference to the lhs object (a in my example). So... Why is this happening?
This has nothing to do with the bitset. Consider this code:
int a = 2;
int b = 3;
std::cout << std::to_string(a *= b) << std::endl; // Prints 6.
std::cout << std::to_string(a *= b) << std::endl; // Prints 18.
You are using an assignment operator, so your variable/bitset changes every time. In your case, the second evaluation yields ((a ^ b) ^ b), which is of course the original a (which did have 6 bits set).
This question already has answers here:
Using Parentheses in Define Preprocessor Statements
(4 answers)
Closed 7 years ago.
Here f(3+3) is replaced by f(6)= 6*6 ?
So the output should be 36 na? So why and how the answer is 15?
#include <iostream>
#define f(a) a*a
using namespace std;
int main(){
cout<<f(3+3);
}
The macro invocation
f(3 + 3)
is replaced by
3 + 3 * 3 + 3
This is the reason that arguments to macros usually is put between parentheses:
#define f(a) (a) * (a)
As a side-note, if you use a variable instead of a literal integer, and does something like
int a = 3;
int result = f(a++);
Then the macro is replaced by
(a++) * (a++)
leading to a being incremented twice. And in an unknown order, leading to undefined behavior.
In C++ there are seldom any use for function-like macros any more, and with all the problems with them (as shown above) you really should not use them. Use functions, they behave correctly, the compiler can still inline them, and they are type-safe (think about what would happen if you did e.g. f("3"), you might get weird errors that are hard to track down).
Because 3 + 3 × 3 + 3 = 15.
Try using parentheses to achieve what you want.
If have encountered this claim multiple times and can't figure out what it is supposed to mean. Since the resulting code is compiled using a regular C compiler it will end up being type checked just as much (or little) as any other code.
So why are macros not type safe? It seems to be one of the major reasons why they should be considered evil.
Consider the typical "max" macro, versus function:
#define MAX(a,b) a < b ? a : b
int max(int a, int b) {return a < b ? a : b;}
Here's what people mean when they say the macro is not type-safe in the way the function is:
If a caller of the function writes
char *foo = max("abc","def");
the compiler will warn.
Whereas, if a caller of the macro writes:
char *foo = MAX("abc", "def");
the preprocessor will replace that with:
char *foo = "abc" < "def" ? "abc" : "def";
which will compile with no problems, but almost certainly not give the result you wanted.
Additionally of course the side effects are different, consider the function case:
int x = 1, y = 2;
int a = max(x++,y++);
the max() function will operate on the original values of x and y and the post-increments will take effect after the function returns.
In the macro case:
int x = 1, y = 2;
int b = MAX(x++,y++);
that second line is preprocessed to give:
int b = x++ < y++ ? x++ : y++;
Again, no compiler warnings or errors but will not be the behaviour you expected.
Macros aren't type safe because they don't understand types.
You can't tell a macro to only take integers. The preprocessor recognises a macro usage and it replaces one sequence of tokens (the macro with its arguments) with another set of tokens. This is a powerful facility if used correctly, but it's easy to use incorrectly.
With a function you can define a function void f(int, int) and the compiler will flag if you try to use the return value of f or pass it strings.
With a macro - no chance. The only checks that get made are it is given the correct number of arguments. then it replaces the tokens appropriately and passes onto the compiler.
#define F(A, B)
will allow you to call F(1, 2), or F("A", 2) or F(1, (2, 3, 4)) or ...
You might get an error from the compiler, or you might not, if something within the macro requires some sort of type safety. But that's not down to the preprocessor.
You can get some very odd results when passing strings to macros that expect numbers, as the chances are you'll end up using string addresses as numbers without a squeak from the compiler.
Well they're not directly type-safe... I suppose in certain scenarios/usages you could argue they can be indirectly (i.e. resulting code) type-safe. But you could certainly create a macro intended for integers and pass it strings... the pre-processor handling the macros certainly doesn't care. The compiler may choke on it, depending on usage...
Since macros are handled by the preprocessor, and the preprocessor doesn't understand types, it will happily accept variables that are of the wrong type.
This is usually only a concern for function-like macros, and any type errors will often be caught by the compiler even if the preprocessor doesn't, but this isn't guaranteed.
An example
In the Windows API, if you wanted to show a balloon tip on an edit control, you'd use Edit_ShowBalloonTip. Edit_ShowBalloonTip is defined as taking two parameters: the handle to the edit control and a pointer to an EDITBALLOONTIP structure. However, Edit_ShowBalloonTip(hwnd, peditballoontip); is actually a macro that evaluates to
SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)(peditballoontip));
Since configuring controls is generally done by sending messages to them, Edit_ShowBalloonTip has to do a typecast in its implementation, but since it's a macro rather than an inline function, it can't do any type checking in its peditballoontip parameter.
A digression
Interestingly enough, sometimes C++ inline functions are a bit too type-safe. Consider the standard C MAX macro
#define MAX(a, b) ((a) > (b) ? (a) : (b))
and its C++ inline version
template<typename T>
inline T max(T a, T b) { return a > b ? a : b; }
MAX(1, 2u) will work as expected, but max(1, 2u) will not. (Since 1 and 2u are different types, max can't be instantiated on both of them.)
This isn't really an argument for using macros in most cases (they're still evil), but it's an interesting result of C and C++'s type safety.
There are situations where macros are even less type-safe than functions. E.g.
void printlog(int iter, double obj)
{
printf("%.3f at iteration %d\n", obj, iteration);
}
Calling this with the arguments reversed will cause truncation and erroneous results, but nothing dangerous. By contrast,
#define PRINTLOG(iter, obj) printf("%.3f at iteration %d\n", obj, iter)
causes undefined behavior. To be fair, GCC warns about the latter, but not about the former, but that's because it knows printf -- for other varargs functions, the results are potentially disastrous.
When the macro runs, it just does a text match through your source files. This is before any compilation, so it is not aware of the datatypes of anything it changes.
Macros aren't type safe, because they were never meant to be type safe.
The compiler does the type checking after macros had been expanded.
Macros and there expansion are meant as a helper to the ("lazy") author (in the sense of writer/reader) of C source code. That's all.
This question already has answers here:
The need for parentheses in macros in C [duplicate]
(8 answers)
Confusion with Macro expansion [duplicate]
(3 answers)
Closed 9 years ago.
This question was asked to me in a mock interview...Really got surprised to find awkward answers...
consider a macro:
#define SQR(x) (x*x)
Example 1:
SQR(2) //prints 4
Example 2:
If SQR(1+1) is given it doesn't sum (1+1) to 2 but rather ...
SQR(1+1) //prints 3
Awkward right? What is the reason? How does this code work?
NOTE: I searched SO but couldn't find any relevant questions. If there are any kindly please share it!
SQR(1+1) expands to 1+1*1+1 which is 3, not 4, correct?
A correct definition of the macro would be
#define SQR(x) ((x)*(x))
which expands to (1+1)*(1+1) and, more important, shows you one of the reasons you shouldn't use macros where they aren't needed. The following is better:
inline int SQR(int x)
{
return x*x;
}
Furthermore: SQR(i++) would be undefined behavior if SQR is a macro, and completely correct if SQR is a function.
The problem is that macros are doing textual substition before it is compiled, so the macro expands to 1+1*1+1
That is why you always put arguments to macros into ():
#define SQR(x) ((x)*(x))
I have define the following macro,
#define abss(a) a >= 0 ? a : -a
while invoking this with,
int b=-1;
int c = abss(b);
printf("%d\n",c);
it should replaced in the form b >= 0 ? b : --b, which should output -2, but it outputs in my Bloodshed/DevC++ compiler 1.
I am analyzing C language for examination purpose, so I have to know what actually happens to the above case in C. Is the output result 1 is for CPP compiler I am using or what???
Your code
int b=-1;
int c = abss(b);
printf("%d\n",c);
gets translated by the preprocessor to:
int b=-1;
int c = b >= 0 ? b : -b;
printf("%d\n",c);
(the int b=-1 is in the C domain whereas the abss(b) gets expanded by the preprocessor before the compiler gets to int b=-1)
Why on earth do you think it should output -2?
#define abss(a) a >= 0 ? a : -a
so this:
int c = abss(b)
becomes
int c = b >= 0 ? b : -b
and b is -1, so that will evaluate to 1
by the way, you should bracket every use of a macro parameter, as you may get passed such things as x + 1. which would evaluate rather strangely.
Not to mention the results of abss(++x)
Your macro expands to
b >= 0 ? b : -b;
Not to b >= 0 ? b : --(-b); or whatever it is you expected.
Are you suggesting that
int x = -4;
-x;
should decrement x?
Bottom line - avoid macro use when possible.
The macro processor will never attach two adjacent tokens together, even if there is no whitespace between them, so indeed, as other posters have mentioned, your macro expands to - b, or 1.
If you want two tokens to become one when expanded by the preprocessor, you have to use the token pasting operator ##, something like
#define abss(a) a >= 0 ? a : - ## a
this will indeed do what you want, in the sense that the negative sign and the variable will form one token. Unfortunately (or fortunately, depending on how you look at it!) the pasted token "-b" will be invalid, and the expansion will not compile.
#define neg(a) -a
int b = -1;
neg(b);
In the above case, the macro is expanded to -b by the preprocessor, which will result in the value of 1. The preprocessor won't even be aware that the sign of the content of b is negative, so where should the second - come from to form a prefix decrement operator?
Even if you wrote it like this:
neg( -b );
Macro replacement is done on token level, not as a textual search & replace. You would get the equivalent of - ( -b ), but not --b.
Edit: The manual you link to in other comments is outdated (does not even address the C99 standard), and is dangerously bad. Just skimming through it I found half a dozen of statements that will make you look real stupid if you assume them to be correct. Don't use it, other than to light a fire.
This macro
#define abss(a) a >= 0 ? a : -a
is indeed hazardous, but the hazards are not where you think they are. The expression from your post
int c = abss(b);
works perfectly fine. However, consider what happens when the expression is not a simple variable, but is a function that is hard to calculate, or when it is an expression with side effects. For example
int c = abss(long_calc(arg1, arg2));
or
int c = abss(ask_user("Enter a value"));
or
int c = abss(b++);
If abss were a function, all three invocations would produce good results in predictable time. However, the macro makes the first call invoke long_calc and ask_user twice (what if the user enters a different number when prompted again?), and it post-increments b twice.
Moreover, consider this seemingly simple expression:
int c = abss(b) + 123;
Since + has a higher precedence than ? :, the resulting expansion will look like this:
int c = b >= 0 ? b : -b + 123;
When b is positive, 123 will not be added, so the meaning of the expression will change dramatically!
This last shortcoming can be addressed by enclosing the expression in parentheses. You should also enclose in parentheses each macro argument, like this:
#define abss(a) ((a) >= 0 ? (a) : -(a))
The reason for you getting the behaviour is preprocessor will just replace a with b and so effectively your code after preprocessing will be like
b >= 0 ? b : -b
and not
b >= 0 ? b : --b
So, when if b = -1, then it will effectively be considered as -(-1) and thus becomes 1.
You can check the preprocessor output and see it for yourself.