VS Command Line Arg to string

I have been going through a couple books trying to learn C++ as I am a C# developer by trade. I have gotten some code to work but would like to understand why it works and why Microsoft uses a different implementation for the command line arguments than than the standard.

Basically the code I have bellow gets the first command line argument being the startup location and puts it into a string. Can someone explain why this works?

1
2
3
4
5
6
7
int _tmain(int argc, _TCHAR* argv[])
{
        auto c = argv[0];
	wstring test(&c[0]);

	string test2(test.begin(), test.end());
}


Thanks.
...why Microsoft uses a different implementation for the command line arguments than than the standard.
I am afraid only MS knows for certain.

Your code works only in VS with Unicode as the Character Set, so TCHAR is actually a wchar_t.
If you use Multi Byte Character Set TCHAR is char and it doesn't compile.

BTW. I would recommend to forget this MS templates and create a empty project with a standard main function.

Also be aware that argv[0] might be null which will crash your app
@Thomas1965,

Thank you for the explanation that does help answer the question. I am told from both the book and the documentation online that argv[0] will always contain the program execution path. This was just an example anyway for me to test. I tried creating a standard main function but when I did that I was unable to pull any command line args from the array. It would only show the first character.
This should do:
1
2
3
4
5
6
7
int main(int argc, char *argv[])
{
  for (int i = 0; i < argc; i++)
  {
    cout << "Arg[" << i << "] " << argv[i] << "\n";
  }
}

About command line args:
https://stackoverflow.com/questions/2050961/is-argv0-name-of-executable-an-accepted-standard-or-just-a-common-conventi

What books do you have?
> why Microsoft uses a different implementation for the command line arguments than than the standard.

The Microsoft implementation does support standard-conforming main()
Unless there is a specific reason, write your main as

either: int main() { // not interested in command line arguments

or int main( int argc, char* argv[] ) { // we want to look at the command line arguments

_tmain and wmain are non-portable Microsoft specific extensions.


> argv[0] will always contain the program execution path.

Yes. argv[0] will never be a null pointer.
Though, it need not be a fully qualified path; and at least in theory, it may be the null string "" if the implementation is unable to determine the name that was used to invoke the program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>

int main( int argc, char* argv[] )
{
    // print the command line arguments
    for( int i = 0 ; i < argc ; ++i )
        std::cout << "argv[" << i << "] == " << argv[i] << '\n' ;
    // notes:
    // it is guaranteed that argc >= 1
    // argv[0] is guaranteed to contain the name used to invoke the program.
    //              (or a valid empty c-style string if the name is unknown)
    // argv[1] ... argv[argc-1] hold the other command line arguments
    // argv[argc] is guaranteed to be a null pointer

    // extract the command line arguments and place them into a vector
    const std::vector<std::string> cmd_line_args( argv, argv+argc ) ;

    // print out the contents of the vector
    for( const auto& arg : cmd_line_args ) std::cout << std::quoted(arg) << ' ' ;
    std::cout << "\n--------------------------------------\n" ;
}


+ ./myprogram
argv[0] == ./myprogram
"./myprogram" 
--------------------------------------
+ ./myprogram one
argv[0] == ./myprogram
argv[1] == one
"./myprogram" "one" 
--------------------------------------
+ ./myprogram one two buckle my shoe
argv[0] == ./myprogram
argv[1] == one
argv[2] == two
argv[3] == buckle
argv[4] == my
argv[5] == shoe
"./myprogram" "one" "two" "buckle" "my" "shoe" 
--------------------------------------
+ ./myprogram 'one two' 'buckle my shoe'
argv[0] == ./myprogram
argv[1] == one two
argv[2] == buckle my shoe
"./myprogram" "one two" "buckle my shoe" 
--------------------------------------

http://coliru.stacked-crooked.com/a/7ce9e440233f915c

For more information, see: http://en.cppreference.com/w/cpp/language/main_function
Thank you @Thomas1965 and @JLBorges. Thomas to answer your question I am reading Beginning C++ by Ivor Horton.
I am reading Beginning C++ by Ivor Horton.

consider something from stackoverflow's peer-reviewed C++ book list https://stackoverflow.com/a/388282 -- other books are often pretty bad.

ACCU only has reviews on Horton's older books (really bad), not the current, spruced up with C++14 ,"Beginning C++". I just browsed the book's examples at https://github.com/Apress/beg-cpp and it looks like it has a few decent ideas, and attempts to use modern C++, but keeps slipping up, keeps pushing the standard library away (the only time he includes algorithm is to call std::min), and may be missing some key concepts like RAII. The examples use a lot of C arrays, some even heap-allocated, and use shared_ptr many times and never once unique_ptr (should be the other way around), to name just a few things that jump out.
Last edited on
It isn’t on Yechiel Kimchi’s bad books list (http://www.cs.technion.ac.il/users/yechiel/CS/BadBooksC+C++.html), but that doesn’t mean it is high quality. It is unfortunate that for beginners it is very difficult to distinguish the two.

JLBorges wrote:
Yes. argv[0] will never be a null pointer.
...if your program is executed by any standard shell or standard utility. It very well may be null if the calling program is careless.

Likewise, if executed by POSIX-conforming processes it will have the exact invocation path, but it need not have anything useful at all. You can usually assume that you can reconstruct the binary path either directly or through the system $PATH, but again, this is not guaranteed and you should code against the possibility of failure.
Microsoft use that non-standard form of main() because it's consistent with their support for UNICODE-16.

They use a macro (_UNICODE) to determine if the code is being compiled with ASCII or UNICODE-16 strings, and that logic has been pushed all the way back to main() and it's string arguments. TCHAR is defined as differently, (char or wchar_t) depending on that macro definition.

The Visual Studio Wizard generates this MS form, but it's usually ok to change it to the standard form.
Registered users can post here. Sign in or register to post.