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?
Related
#define prod(a) (a*a)
using namespace std;
int main()
{
int i = 3, j, k, l;
j = prod(i++);
cout << i << endl;
k = prod(++i);
cout << i << endl;
l = prod(i+1);
cout << i << " " << j << " " << k << " " << l;
}
Why is variable "i" incremented twice?
i.e to 5 from 3 after j=prod(i++);
Remember that macros are expanded in the source code, not actually called or evaluated.
That means a "call" like
prod(i++)
results in the expanded code
i++*i++
being seen by the compiler.
Many compilers allow you to stop after preprocessing, or otherwise generate preprocessed source, that you can examine to see macro expansions.
If you continue using such a macro with other expressions as arguments, you will soon see another reason they are bad.
Lets say you use
prod(2+4)
Then that will result in the expansion
2+4*2+4
which is equal to
2+(4*2)+4
which is equal to 14, not 36 which might have been expected.
Why is variable "i" incremented twice? i.e to 5 from 3 after j=prod(i++)
Because prod() is a macro, not a function, so
k=prod(++i);
become
k=(++i * ++i);
Here's my code:
int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 1;i<argc;i++) printf("Argument %d:%s\n",i,argv[i]);
// output = Argument 1:param
for (int k = 1; k < argc; k++) cout << "Argument " << k << ": " << argv[k];
// output = Argument 1: 00BF5878
return(0);
}
My question is: why do I see different outputs on cout and printf?
You see an address in the output from cout because you have built the program with UNICODE or _UNICODE defined. Probably by way of a setting in a Visual Studio project. Then _tmain expands to MIcrosoft's non-standard wmain, and _TCHAR expands to wchar_t.
And cout doesn't know how that a pointer to wchar_t is supposed to point to a null-terminated string of wide characters.
I am not sure why that doesn't happen with printf. Lemme check.
OK I have checked and your printf is not printing "param" as you indicate it does.
Here's the corrected code I checked with:
#include <iostream>
#include <stdio.h>
#include <tchar.h>
using namespace std;
int _tmain( int argc, _TCHAR* argv[] )
{
for( int i = 0;i < argc; ++i )
{
printf("printf Argument %d:%s\n",i,argv[i]);
}
for( int i = 0; i < argc; ++i )
{
cout << "cout Argument " << i << ": " << argv[i] << endl;
}
}
And here's the result:
[D:\dev\test]
> cl foo.cpp /D _UNICODE
foo.cpp
[D:\dev\test]
> foo param
printf Argument 0:f
printf Argument 1:p
cout Argument 0: 004F9A9C
cout Argument 1: 004F9AA4
[D:\dev\test]
> _
In other words, the apparent conundrum is entirely caused by your inaccurate reporting of results.
Solution: instead of using Microsoft's non-standard wmain, and in particular instead of using the now totally meaningless Windows 9x support macros!, use a standard C++ main.
The difference is that printf takes the contents of the parameters and forces the data to match the format specifier. The content of argv[i] will be treated as a nul terminated string because of the %s format specifier.
The cout in conjunction with the stream insertion operator will output based on the type of the parameter. The compiler will search all the operator<<() methods for cout and choose the one the best matches the parameter.
In your case, the compiler is looking for the method operator<<(TCHAR *) and didn't find an exact match. Instead, the compiler recognized that the parameter was a pointer and chose operator<<(void *) which prints out a pointer.
Try defining operator<<(TCHAR*) and see what happens.
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);
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>
I'm running C++ program in VS2005, and I've set only one argument in project properties-> debug-> command line args, and it's named profile1.dll for example.
here's a code snippet
cout<<"number of arguments:" << argc<<endl;
for (int i=0; i<argc; i++)
cout << "argument " << i << ": " << argv[i] << endl;
In the output I get
number of arguments:2
argument 0: c
argument 1: p
don't know why it doesn't print the name of the argument?
Does the name of your exe start with C? If you expect a string and you only get one character, it's usually because you've discovered that the Western alphabet in UTF-16 Unicode effectively puts a 0 between alternating ANSI chars. Are you compiling for Unicode ?
argv[0] is the name of your program. argv[1] is the first parameter. It sounds like you have declared the relevant parameter in main() as char* argv rather than char *argv[] or char **argv.
Leave TCHAR be, it's fine.
If you compile with unicode, use wcout for output:
int _tmain(int argc, _TCHAR* argv[])
{
for (int i=0; i<argc; i++)
wcout << "argument " << i << ": " << argv[i] << endl;
return 0;
}
Otherwise compile without unicode and your code will just work as-is (and will not work with unicode parameters :o)
You can find setting in "Project Properties/General/Character Set"
Can you put the prototype of your main function? What you are doing is apparently fine.
Make sure your main's function prototype is something similar to:
int main(int argc, char **argv)
Hope it helps.