macro output doesn't work - c++

I'm learning c++,The macro behavior not as expected.
1 #include<cstdlib>
2 #include<iostream>
3 #include<cstring>
4 #define die(x) std::cout << x << std::endl ; exit(-1)
5 const char *help = "Usage: coffee --help --version";
6 const char *version = "alpha";
7 int main(int argc,char **argv)
8 {
9 if(argc<2||!strcmp(argv[1],"--help"))
10 die(help);
11 if(!strcmp(argv[1],"--version"))
12 die(version);
13
14 return 0;
15
16 }
g++ -o sample ./*
./sample --help
Output:Usage: coffee --help --version
./sample --version
Output:
I'm confused why --version didn't output string alpha.

When std::cout << x << std::endl ; exit(-1) is expanded by the macro preoprocessor in these two lines
9 if(argc<2||!strcmp(argv[1],"--help"))
10 die(help);
the resulting code is:
if(argc<2||!strcmp(argv[1],"--help"))
std::cout << help << std::endl;
exit(-1);
Which is probably not what you wanted;
The common trick for "multistatement macros" is to use do { ... } while(0) around the statements you want to have in a macro.
You can use gcc -E or cl -E to get the output from the C preprocessor, so you can see what the compiler ACTUALLY sees.
Edit: I should point out that I personnaly would prefer, in this case, a "die(msg) function" rather than fixing up the macro. Then you can, for example, set a breakpoing in die() and find out how you got there when something isn't working right! You can't set a breakoint in a macro.

Just try to brutally replace the body of the macro and you will see why:
if(argc<2||!strcmp(argv[1],"--help"))
die(help);
becomes:
if(argc<2||!strcmp(argv[1],"--help"))
std::cout << help << std::endl;
exit(-1);
With no braces { } for the if statement, the body is made just of one instruction so the exit(-1) is always executed.
You would have discovered if by using an if / else if instead that and if / if couple since the second else if would have missed its parent.

You forgot { }. Expand the macro manually and you'll see the result:
if(argc<2||!strcmp(argv[1],"--help"))
std::cout << help << std::endl ; exit(-1);
i.e.
if(argc<2||!strcmp(argv[1],"--help"))
std::cout << help << std::endl ;
exit(-1);

Your code after substitution of macro
if(argc<2||!strcmp(argv[1],"--help"))
std::cout << help << std::endl ; exit(-1) ; //<-- this exit will work always.
if(!strcmp(argv[1],"--version"))
std::cout << version << std::endl ; exit(-1) ;
correct way:
#define die(x) do {std::cout << x << std::endl ; exit(-1); } while(false);

Related

C++ Compilation error with std::cout and doublification macro

I'm compiling the following in MSVC 2012
#define DOUB (i) ((i)+(i))
int _tmain(int argc, _TCHAR* argv[])
{
for (int i(0); i <= 10; i++)
std::cout << "twice" << i << "is" << DOUB(i) << '\n'; // 22
system("PAUSE");
return 0;
}
and getting the following error for line 22 : error C2064: term does not evaluate to a function taking 1 arguments
Can anyone help?
Preprocessor macro definitions care about whitespace: Don't leave a whitespace between the macro name and the parentheses for function-like macros:
#define DOUB(i) ((i)+(i))
// ^^^^^^^
You left a space after DOUB. As far as your compiler is concerned, your code reads as:
std::cout << "twice" << i << "is" << (i) ((i)+(i))(i) << '\n';
You shouldn't blame the preprocessor, just avoid it! (or delete the space)
For completeness, what you created is called a text replacement macro, but you won't be using macros anymore will you?

Make a C++ macro that acts like a stream

In the absence of help from Google, I wonder if someone could tell me if it is possible to create a C++ (g++) debug macro that acts like, for example, an "improved" std::cout. Idea is to accept args via << and to append some text so that
DBG << "Hello" << world;
might produce
myfile.cpp 1420 Hello world
I know there are logging libraries(?)/macros(?) out there that do this sortof thing. I'm interested in how it's done, not using some package.
Your macro could create a temporary variable which invokes endl on destruction. The temporary will stick around until the enclosing expression ends, typically at the ;.
#include <iostream>
struct X {
~X() { std::cout << std::endl; }
};
#define DBG (X(), std::cout << __FILE__ << " " << __LINE__ << " ")
int main () {
std::string world(", world");
DBG << "Hello" << world;
}
How about:
#define DBG std::cout << __FILE__ << " " << __LINE__ << " "
http://ideone.com/mN5n3
Close enough! Unfortunatelly, you have to declare the variable world beforehand.
The idea behind a debug macro is that it should compile to nothing if you are in release mode. Try this;
#ifdef _DEBUG
#define MESSAGE(x) (std::cout << __FILE__ << " " << __LINE__ << " " << x);
#else
#define MESSAGE(x) ;
#endif
int _tmain(int argc, _TCHAR* argv[])
{
MESSAGE("Hello");
return 0;
}
When you are in release mode, MESSAGE(x) will have no effect, but in debug mode, you will get a message to the command line.

Strange behavior of multi-line code block in the if clause without parentheses

When I compile the following code snippet and run it, I expect it to print statement at line no. 12 too. But that doesn't happen? Why is that so? How does compiler handles a comment in if block?
1 #include <iostream>
2 using namespace std;
3
4 int main() {
5 int a;
6 if (false)
7 cout << "This will not be printed." << endl;
8 cout << "This will be printed anyway." << endl;
9
10 if (false)
11 // comment
12 cout << "This should also be printed. But not. Why?" << endl;
13 a = 100;
14
15 cout << "a = " << a << endl;
16 }
produces:
hyper150:~ 1041$ g++ what_if.cpp
hyper150:~ 1042$ ./a.out
This will be printed anyway.
a = 100
There is no trace of comments what so ever in the produced native language code.
Your code is equivalent to this:
1 #include <iostream>
2 using namespace std;
3
4 int main() {
5 int a;
6 if (false)
7 cout << "This will not be printed." << endl;
8 cout << "This will be printed anyway." << endl;
9
10 if (false)
11 cout << "This should also be printed. But not. Why?" << endl;
12 a = 100;
13
14 cout << "a = " << a << endl;
15 }
And since the condition at line 10 [new code] is never met - the cout at line 11 never occures
It's not printed because you have if(false) in front of it and if (false) never evaluates to true.
Compiler ignores comments.
And one more advice: In if statements like this one it's better when you write curly braces even if there is just a single statement.
if (false)
cout << "This should also be printed. But not. Why?" << endl;
is better to write like:
if (false)
{
cout << "This should also be printed. But not. Why?" << endl;
// Most likely you are going to add more statements here...
}
If you don't use brackets, the if will only take the next expression:
if (false)
cout << "This will not be printed." << endl;
cout << "This will be printed anyway." << endl;
if (false)
// comment
cout << "This should also be printed. But not. Why?" << endl;
a = 100;
is equivalent to:
if (false)
{
cout << "This will not be printed." << endl;
}
cout << "This will be printed anyway." << endl;
if (false)
{
// comment
cout << "This should also be printed. But not. Why?" << endl;
}
a = 100;
Comments are removed long before the actual compilation.
If you do not use braces to surround the conditional result, then the conditional result terminates with the end of the next statement, which usually means the ; character.
But it is not only the ; character, because you can do this (which is really horrible to read):
if (true)
for(int i = 0; i < 5; i++)
if (i == 4)
break;
else
h = i;
In this case the for loop is the next occurring statement, which is a iteration-statement that terminates after the h=i statement.
Everyone has their own tastes with the bracket conventions - I prefer to use bracketless if statements only if there is only one line under it which does not need a comment (if there are else statements, then I use brackets).
Code optimization is one of the phases of compilation. During this your commented code is removed from the code which actually produces the binary. So it interprets it as
if (false)
cout << "This should also be printed. But not. Why?" << endl;
And you have put a false within the if condition so ....you know the consequences.
Line endings are not significant in C++; the if controls the following
statement. In your second case, the following statement is the output,
so it should not be printed. Comments are not statements (an are in
fact replaced with white space before actual parsing). Thus:
if ( false ) std::cout << "no" << std::endl;
if ( false )
std::cout << "no" << std::endl;
if ( false )
std::cout << "no" << std::endl;
will output nothing.

very weird hang at a for loop initialization

I have a very weird bug that I can't seem to figure out. I have narrowed it down to a small section of code (unless the compiler is reordering my statements, which I don't believe is true).
...
std::cout << "here"<< std::endl;
std::vector<int>::iterator n_iter;
std::vector<int>::iterator l_iter;
std::cout << "here?" << std::endl;
for(n_iter = n.begin(), std::cout << "not here" ; std::cout << "or here" && n_iter < n.end(); n_iter++)
{
std::cout << "do i get to the n loop?";
...
}
When I run this, I see the first "here", the second "here?", but I don't get the "not here" or the "or here" output. And I definitely don't get the "do i get to the n loop?".
The weird thing is that my program is working (it is almost using up an entire cpu core... ), but it doesn't finish, it just hangs.
I've tried using clang++ and g++, and I'm not using any optimizations. I have the boost library installed (and am using the boost_program_options part of it), along with armadillo. But I don't think the compiler should be reordering things...
It happens with or without the cout calls inside the for loop declaration, and it doesn't just skip the loop.
The vector "n" has a length of at least 1, and is given by a boost_program_options call.
Any ideas?
The first thing you should try is to output std::endl after each string. This flushes the buffer for the output.
The following program (which has some extra newlines that yours didn't):
#include <string>
#include <iostream>
#include <vector>
int main() {
std::vector<int> n;
n.push_back(3);
n.push_back(3);
n.push_back(3);
std::cout << "here"<< std::endl;
std::vector<int>::iterator n_iter;
std::vector<int>::iterator l_iter;
std::cout << "here?" << std::endl;
for(n_iter = n.begin(), std::cout << "not here\n" ; std::cout << "or here\n" && n_iter < n.end(); n_iter++)
{
std::cout << "do i get to the n loop?\n";
}
}
Has the following output:
[5:02pm][wlynch#orange /tmp] make foo
g++ foo.cc -o foo
[5:02pm][wlynch#orange /tmp] ./foo
here
here?
not here
or here
do i get to the n loop?
or here
do i get to the n loop?
or here
do i get to the n loop?
or here
This appears to be what you expect, so I'm not sure where you are having issues on your end, but it may be in skipped code.

Determining calling line without macro

Is it possible to determine the line number that calls a function without the aid of a macro?
Consider this code:
#include <iostream>
#define PrintLineWithMacro() \
std::cout << "Line: " << __LINE__ << std::endl; // Line 4
void PrintLine()
{
std::cout << "Line: " << __LINE__ << std::endl; // Line 8
}
int main(int argc, char **argv)
{
PrintLine(); // Line 13
PrintLineWithMacro(); // Line 14
return 0;
}
which outputs the following:
Line: 8
Line: 14
I understand why each prints what they do. I am more interested if it's possible to mimic the macro function without using a macro.
I would do the following:
#define PrintLine() PrintLine_(__LINE__)
void PrintLine_(int line) {
std::cout << "Line: " << line << std::endl;
}
I know that this doesn't completely remove the preprocessor, but it does move most of the logic into an actual function.
Not portably. On any given platform, you could basically re-implement the details of a debugger - the information is effectively stored on your stack as the return address. You can get at that kind of thing with the backtrace() function on some platforms.
C++ has caught up with this question in the c++20 standard.
In c++20 you may now do:
#include <iostream>
#include <source_location>
void PrintLine(std::source_location location = std::source_location::current())
{
std::cout << "Line: " << location.line() << std::endl; // Line 8
}
int main(int argc, char **argv)
{
PrintLine(); // Line: 11
PrintLine(); // Line: 12
return 0;
}
Another question is whether the compiler of your interest has caught up with the standard.
Note that the construct was present pre c++20 and you could try:
#include <experimental/source_location>