Click here to Skip to main content
15,888,112 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am studying how to utilize argc and argv[] parameters to program a convenience UI in Command windows in WIN8.1 x64 system. Here's my source code in VS2013 c++:

C++
int _tmain(_In_ int argc, _In_reads_(argc) char* argv[])
{
	PCHAR parm;

	printf("argc in main is %d\n", argc);

	for (int i = 0; i < argc; i++){
	        parm = argv[i];
		printf("&argv[%d] = %x\n", i, &argv[i]);
		printf("argv[%d] = %x\n", i, argv[i]);
		printf("*argv[%d] = %c\n", i, *argv[i]);
		printf("parm[0] = %c, parm[1] = %c, parm[2] = %c \n", parm[0], parm[1], parm[2]);
	}

	return 0;
}


Let's assume the exe file is test.exe. While I type in
"test.exe /a"
in command window, I can get argc = 2. When I want to print out the valued stored in argv[], the weird thing happened. Supposedly I should get the output like the following:

&argv[0] = b76148
argv[0] = b76154
*argv[0] = t
parm[0] = t, parm[1] = e, parm[2] = s
// first 3 CHAR of test.exe

&argv[0] = b7614c
argv[0] = b76184
*argv[0] = /
parm[0] = /, parm[1] = a, parm[2] =

// first 3 CHAR of /a

However, I get the following in actual:

&argv[0] = b76148
argv[0] = b76154
*argv[0] = t
parm[0] = t, parm[1] = , parm[2] = e

&argv[0] = b7614c
argv[0] = b76184
*argv[0] = /
parm[0] = /, parm[1] = , parm[2] = a


Because parm is a PCHAR, supposedly I can print out the characters stored in agrv[] one by one, but why parm[1] always be zeros and parm[2] is the CHAR next to parm[0]. I guess it is a memory size issue, but while sizeof(CHAR)=1, I can't figure out why the memory location of 1st CHAR is 2 bytes away from 2nd CHAR.

Thanks for the patient to view this question & I appreciate your help to tell me why I am wrong. Thanks all!
Posted
Updated 5-Nov-14 21:05pm
v2

The argv parameter of _tmain is not of type char* but _tchar*. With Unicode builds this will be a wide character occupying two bytes per character. With ASCII characters the first (low) byte is the ASCII code and the second (high) byte is zero.

See also the MSDN[^].
 
Share this answer
 
Comments
EricckWu 6-Nov-14 21:26pm    
Dear Jochen,
Thanks for your help & it worked! However, I still have one question about the char* & _tchar*
My code is "int _tmain(_In_ int argc, _In_reads_(argc) char* argv[])". Even I claimed argv[] as "char*", it will still be converted to "_tchar*" because of "_tmain" function. Is that correct?
Jochen Arndt 7-Nov-14 3:08am    
The C main function is a little bit special. By using _tmain instead of main you tell the Microsoft compiler that you want to use the version that corresponds to the project Unicode settings which are Unicode / wide char by default with VS 2013. So the command line arguments are stored as wide chars and the pointers are passed to your main function. There is no conversion. With any other function you should get a compiler warning, but again, main is special.

Overall, you should use one of the functions described in the MSDN link of my answer without changing any parameter types.
EricckWu 7-Nov-14 9:57am    
Dear Jochen,
So the command line arguments are stored as wide chars no matter I claimed "char* argv[]" or "_TCHAR* argv[]" in the argument of _tmain?
However, I think you are right, the rule of thumb is "never change any parameter types defined in MSDN"
Thanks so much!

Best Regards,
Jochen Arndt 7-Nov-14 10:14am    
Yes, you are right.
However, if you change your project settings from Unicode to ANSI, the arguments will be stored as chars.

_tmain is a Unicode dependant definition defined in tchar.h. With Unicode builds it will be replaced by wmain and with ANSI build it will be replaced by main.
First off bin all the MS specific rubbish until you're sure that everything works as advertised in standard C++. That's if you really want to use C++ as aside from one construct that's a C program.

So try something like:

C++
#include <algorithm>
#include <iostream>
#include <iterator>

int main( int argc, char *argv[] )
{
	std::copy( argv, argv + argc, std::ostream_iterator<const char *>( std::cout, "\n" ) );
}

which is standard C++'03 and will display the command line parameters you pass to the program. You can take it from there...
 
Share this answer
 
v3
Comments
Richard MacCutchan 6-Nov-14 5:05am    
I could only get that to work by modifying the source to:

std::copy( argv, argv + argc, std::ostream_iterator<const char*>( std::cout, "\n" ) );
</const>

but I have to admit my understanding of STL is very basic, and that really is an elegant piece of code.
Aescleal 6-Nov-14 6:11am    
Bugger, I missed the ="" artifact when I cut and pasted the code in. Sorry about that!
Stefan_Lang 6-Nov-14 5:36am    
I suspect the trailing ="" was sneaked into the code by the buggy editor window. Happened to me several times, and I've seen it happen in other people's postings over and over. I've reported it as a bug a long time ago, but since I couldn't find a sure way to reproduce it has been ignored so far.
Richard MacCutchan 6-Nov-14 6:34am    
Yes that happened to me also, I thought I had done something wrong while editing the message.
EricckWu 6-Nov-14 22:10pm    
Dear Aescleal,
Thanks for your help and it works! It is really a beautiful code.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900