Need explanation over the behavior of C++ code - c++

I need a little explanation over how this C++ code is behaving and returning value
#include<iostream>
using namespace std;
#define MY_MACRO(n) #n
#define SQR(x) x * x
int main()
{
//cout<<MY_MACRO(SQR(100))<<endl;
//cout<< sizeof(SQR(100))<<endl;
cout<< sizeof(MY_MACRO(SQR(100)))<<endl;
return 0;
}
As far i am concerned #n returns the number of arguments in the MY_MACRO(n) But if before that SQR(100) will be replaced by 100 * 100 (9 characters if we count spaces) But now sizeof(9) should print 4 but Its returning 9 with cout<< sizeof(MY_MACRO(SQR(100)))<<endl;
What's the catch behind it?

You are not using the right definition of #n. It is not the number of arguments. It makes it into a string.

After macro substitution your code will be converted to
sizeof("SQR(100)");
which will give 9 as size of string literal including the terminating '\0'.
#n will make the argument as string, its not the number of argument
For example :
#define display( n ) printf( "Result" #n " = %d", Result##n )
int Result99 = 78;
display( 99 ) ; // Will output -> Result99 = 78

Related

Why, when one memory subset of a string is passed to a int variable, does printing give me a completely different value?

I want the first character in string example1 to print out. Using example1[0] seems to work, but for some reason having an int variable have that same value will output 49. Why does this happen, and how can I make the LOG(print) print 1 instead of 49?
#include <iostream>
#include <string>
#define LOG(x) std::cout<<x<<std::endl;
int main() {
std::string example1 = {"1 2 3 4 5"};
int print = 0;
LOG(example1[0]);
//this prints 1
print = example1[0];
LOG(print)
//this, somehow, prints 49. Why?
}
When you write example1[0], that's a char; if you convert it to an int, it's the ASCII value of it (or, in older/different systems, the value in the specific character table).

C++ Preprocessor macro selection by argument

I'm trying to define a preprocessor macro that in turn selects the right macro depending on the value of an argument.
#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"
#define BIT(n) ?????
int main() {
printf("%d %s", BIT(9));
return 0;
}
BIT(n) should expand to:
BIT_8(n) if n≤8
BIT_N(n) if n>8
Any way to achieve this?
Unless you want very clumsy code, you can't do that. The preprocessor has no idea about the value of the argument passed in. It's just doing string replacement and that's all.
That being said, they are crazy guys implementing BIT_x for all x in [0 to 63].
This is very ugly and would fail is used with an argument set at 64.
A clean solution is to use a function instead:
const char * bit_msg(unsigned int b)
{
if (b > 8) return "is greater than 8";
const char * bits[] = {
"is 0 and lower than 8",
"is 1 and lower than 8",
"is 2 and lower than 8",
"is 3 and lower than 8",
"is 4 and lower than 8",
"is 5 and lower than 8",
"is 6 and lower than 8",
"is 7 and lower than 8",
"is 8",
};
return bits[b];
}
#define BIT(X) X, bit_msg(X)
[...]
printf("%d %s", BIT(9));
Because you've tagged the question with C++ and to follow #Romen you could achieve similar result using constexpr that, if possible, will be computed by the compiler at compile time, resulting in code that's as efficient as a macro.
In the example above, you'll just need to replace the signature with constexpr const char * bit_msg(unsigned int b) and the compiler might even skip the function and write (the equivalent of) printf("%d %s", 9, "is greater than 8").
The challenge is that the pre-processor doesn't know math. You can solve this problem by implementing the math you need, but it gets UGLY. For example, here's working pre-processor code for what you want to do:
#include <stdio.h>
#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"
// Identify values less than 8; make the second argument 8
#define LT_8_0 ~,8
#define LT_8_1 ~,8
#define LT_8_2 ~,8
#define LT_8_3 ~,8
#define LT_8_4 ~,8
#define LT_8_5 ~,8
#define LT_8_6 ~,8
#define LT_8_7 ~,8
#define LT_8_8 ~,8
// Helper macros. Delays let arguments be processed before the macros is run.
#define MERGE(A, B) A ## B
#define MERGE_DELAY(A, B) MERGE(A,B)
#define ARG2(A,B,...) B
#define ARG2_DELAY(A,B,...) ARG2(A,B,__VA_ARGS__)
// Return 8 or N depending if n <= 8...
#define LT_8(n) ARG2_DELAY( MERGE(LT_8_, n), N,~ )
#define BIT(n) MERGE_DELAY(BIT_, LT_8(n))(n)
int main() {
printf("%d %s\n", BIT(9));
return 0;
}
Note that the LT_8 macro works by taking the second of a series of arguments. We default that second argument to N, but if we recognize the input number to be 8 or less, we insert a new second argument of 8.
you could do this
#include <stdio.h>
#define BIT_8(n) printf("%d is lower than or equal to 8 \n" , n)
#define BIT_N(n) printf("%d is greater than 8 \n" , n)
#define BIT(n) ((n <= 8) ? (BIT_8(n)) : (BIT_N(n)))
int main() {
BIT(7);
BIT(8);
BIT(9);
return 0;
}

What is the principle of tellp() calculating the length of stringstream?

I think the length ofstringstream is calculating by the blocks.that means how many blocks in it, how long it is.the blocks is splited by '\t' '\s' '\n'.
for example, stringstream = '23\t45\t5.677\t' , its length should be 6. The delimiter should be counted.
I just can verify my idea while the type of arguments are all int.
here is my code.
I wonder that s_double.tellp() is not 10.
#include<iostream>
#include<sstream>
#include<cstdlib>
using namespace std;
int main()
{
stringstream s_int;
stringstream s_double;
srand((unsinged)time(NULL));
for(int index = 0;index<5;index++)
{
double random = rand() / (double) RAND_MAX * 5;
s_int<<index<<'\t';
s_double<<random<<'\t';
}
cout<<s_int.tellp()<<'\n';
cout<<s_double.tellp()<<'\n';
exit(0);
}
output:
10
40
after I changed the range of random, the output of s_double changed too.
double random = rand() / (double) RAND_MAX *9;
output:
10
42
The easiest but not faster method is:
auto nLength = strm.str().length();
Regarding s_double position - it is easy to answer your question by examining the content of this stream in a debugger or print it. You will see that double could be "0.554213" for 0.554212545 or "1" for 1 so string length for defferent doubles is complitely different.

max defined in #define not working properly

I wrote the program as follows :
#include<cstdio>
#define max(a,b) a>b?a:b
using namespace std;
int main()
{
int sum=0,i,k;
for(i=0;i<5;i++)
{
sum=sum+max(i,3);
}
printf("%d\n",sum);
return 0;
}
I got the output : 4
But when I stored max(i,3) in a variable k and then added to sum, I got the correct output:
#include<cstdio>
#define max(a,b) a>b?a:b
using namespace std;
int main()
{
int sum=0,i,k;
for(i=0;i<5;i++)
{
k=max(i,3);
sum=sum+k;
}
printf("%d\n",sum);
return 0;
}
Output : 16
Can somebody please explain why is it happening?
hash-define macros are a string expansion, not a "language" thing.
sum=sum+max(i,3);
expands to:
sum=sum+i>3?i:3;
And if you are writing that with no () round it you deserve to get the wrong answer. Try this:
#define max(a,b) (a>b?a:b)
but there are still many situations where it will fail. As others point out an even better macro is:
#define max(a,b) ((a)>(b)?(a):(b))
but it will still fail in too many situations, such as arguments with side effects getting evaluated twice. You are much much better off avoiding macros where possible and doing something like this:
template <typename T> T max(T a, T b) { return a>b?a:b; }
or, infact, using std::max and std::min which have already been written for you!
This line:
sum=sum+max(i,3);
expands to:
sum = sum + i > 3 ? i : 3;
Which, when set up with parens to make it clearer is:
sum = (sum + i) > 3 ? i : 3;
So on the 5-passes through the loop, the expressions are:
sum = (0 + 0) > 3 ? 0 : 3; // Result, sum = 3
sum = (3 + 1) > 3 ? 1 : 3; // Result: sum = 3
sum = (3 + 2) > 3 ? 2 : 3; // Result: sum = 3
sum = (3 + 3) > 3 ? 3 : 3; // Result: sum = 3
sum = (3 + 4) > 3 ? 4 : 3; // Result: sum = 4
And that's where your answer comes from.
The conventional way to solve this is to change the #define to:
#define max(a,b) (((a)>(b))?(a):(b))
But even this has some pitfalls.
I think you are having operator precedence issues, you have to remember that define will lead to a textual replacement in your source code. You should change your define to
#define max(a,b) ((a) > (b) ? (a) : (b))
The output of the prepocessor (view it with the -E flag) will be:
sum = sum+i>3?i:3;
which is the same as
sum = (sum+i)>3?i:3;
which is not what you meant because + has a higher precedence than >. You should use:
#define max(a,b) (a>b?a:b)
instead.
Replacing your macro in the line sum=sum+max(i,3); gives the following form :
sum=sum+i>3?i:3 ;
which is asking that if sum + i is greater than 3 than assign sum's value accordingly. Hence, you have 4 because each time a new assignment happens inside the loop. Use the template method suggested by Andrew.
(The loop evaluates the condition (sum + i) > 3 ? i : 3 every time. There is no cumulative addition here.)

Macro output explanation

Can someone explain the output of this program -
#include<stdio.h>
#include<conio.h>
#define FUDGE(k) k+3.14159
#define PR(a) printf(#a" = %d\t ",(int)(a))
#define PRINT(a) PR(a);putchar('\n')
int main()
{
int x=2;
PRINT(x*FUDGE(2));
printf(\n);
PR(x*FUDGE(2));
return 0;
}
OUTPUT -
x*2+3.14159 = 7
x*FUDGE(2) = 7
Why is FUDGE(2) getting printed in second and not in the first statement.
The # operator is strange. It works before expanding the parameter.
So when calling PR(x*FUDGE(2)), # is applied to x*FUDGE(2) before FUDGE is expanded.
However, in PRINT(x*FUDGE(2)), FUDGE is expanded before passing it on to PR. When PR applies # to it, it has already been expanded.
Because in the first you use PRINT which expands the argument when it "calls" PR.