argv/pointer problems

R

Robin Sanderson

Sorry in advance if this is a stupid question - I am new to C++.

In the process of converting program to be run from the command line
into a function to be run from another program I noticed behaviour
that I do not understand. Consider the example programs below:

Program 1 below is a simple program that merely outputs the command
line arguments. This compiles and runs fine with Microsoft Visual C++
6.0 and g++ 3.3.1.

Program 2 brings up a compile time error in both; in MVC++ it is

"test_cline_2.cpp: In function `int main()':
test_cline_2.cpp:19: error: non-lvalue in increment",

and in g++ it is

"test_cline_2.cpp(19) : error C2105: '++' needs l-value".

Program 3 compiles and runs fine.

Can anyone tell me why Program 2 does not compile? A friend has tried
the code on C++ .NET and apparently it *did* compile.

Thanks in advance,

Robin Sanderson

-----

//Program 1
#include <iostream>
using std:: cout; using std::endl;

int main(int argc, char * argv[])
{
int i;

for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}

return 0;
}

-----

//Program 2
#include <iostream>
using std:: cout; using std::endl;

int main()
{
int i;

int argc=3;
char * argv[3];

argv[0] = "program_name";
argv[1] = "argument_1";
argv[2] = "argument_2";

for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}

return 0;
}

-----

//Program 3
#include <iostream>
using std:: cout; using std::endl;

void vFunction(int argc,char * argv[]);

int main()
{
int iInt;
char * cArray[4];

iInt=3;
cArray[0] = "program_name";
cArray[1] = "argument_1";
cArray[2] = "argument_2";
cArray[3] = NULL;

vFunction(iInt,cArray);

return 0;
}

void vFunction(int argc, char ** argv)
{
int i;

cout << "Using argv++:" << endl;
for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}
cout << endl;

return;
}
 
R

Rolf Magnus

Robin said:
Sorry in advance if this is a stupid question - I am new to C++.

In the process of converting program to be run from the command line
into a function to be run from another program I noticed behaviour
that I do not understand. Consider the example programs below:

Program 1 below is a simple program that merely outputs the command
line arguments. This compiles and runs fine with Microsoft Visual C++
6.0 and g++ 3.3.1.

Program 2 brings up a compile time error in both; in MVC++ it is

"test_cline_2.cpp: In function `int main()':
test_cline_2.cpp:19: error: non-lvalue in increment",

and in g++ it is

"test_cline_2.cpp(19) : error C2105: '++' needs l-value".

Program 3 compiles and runs fine.

Can anyone tell me why Program 2 does not compile? A friend has tried
the code on C++ .NET and apparently it *did* compile.

Thanks in advance,

Robin Sanderson

-----

//Program 1
#include <iostream>
using std:: cout; using std::endl;

int main(int argc, char * argv[])
{
int i;

for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}

return 0;
}

In this program, argv is a pointer.
-----

//Program 2
#include <iostream>
using std:: cout; using std::endl;

int main()
{
int i;

int argc=3;
char * argv[3];

argv[0] = "program_name";
argv[1] = "argument_1";
argv[2] = "argument_2";

for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}

return 0;
}

In this program, argv is an array. You can't increment an array.
-----

//Program 3
#include <iostream>
using std:: cout; using std::endl;

void vFunction(int argc,char * argv[]);

int main()
{
int iInt;
char * cArray[4];

iInt=3;
cArray[0] = "program_name";
cArray[1] = "argument_1";
cArray[2] = "argument_2";
cArray[3] = NULL;

vFunction(iInt,cArray);

return 0;
}

void vFunction(int argc, char ** argv)
{
int i;

cout << "Using argv++:" << endl;
for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}
cout << endl;

return;
}

Here, argv is again a pointer.
 
R

Robin Sanderson

I have just noticed that I posted the wrong version of Programm 3 -
the "** argv" should have been "* argv[]", and this is corrected below
- although this does not alter whether or not it compiles.

This may be a(nother) daft question, but what is it that makes the
difference between the use of "char * argv[3]" in Program 2 and "char
* argv[]" in Program 3? Is it possible to declare argv as a pointer
in Program 2 (so it can be used in an identical way as in the other
programs)?

Thanks,

Robin

-----

//Program 3
#include <iostream>
using std:: cout; using std::endl;

void vFunction(int argc,char * argv[]);

int main()
{
int iInt;
char * cArray[4];

iInt=3;
cArray[0] = "program_name";
cArray[1] = "argument_1";
cArray[2] = "argument_2";
cArray[3] = NULL;

vFunction(iInt,cArray);

return 0;
}
void vFunction(int argc, char * argv[])
{
int i;

cout << "Using argv++:" << endl;
for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}
cout << endl;

return;
}
 
R

Rolf Magnus

Robin said:
I have just noticed that I posted the wrong version of Programm 3 -
the "** argv" should have been "* argv[]", and this is corrected below
- although this does not alter whether or not it compiles.

This may be a(nother) daft question, but what is it that makes the
difference between the use of "char * argv[3]" in Program 2 and "char
* argv[]" in Program 3?

In program 3, it's a parameter, while in program 2, it's a local
variable. You cannot pass arrays as parameters to functions, and
therefore, a "convenience" was added to C (and inherited to C++). If
you write a parameter in a form that looks like an array, it will
actually be a pointer. That's btw the reason why you can leave out the
size. When defining an array, you _always_ need a size for it.
Is it possible to declare argv as a pointer in Program 2 (so it can be
used in an identical way as in the other programs)?


int main()
{
int i;

int argc=3;
char * args[3];

args[0] = "program_name";
args[1] = "argument_1";
args[2] = "argument_2";

char * (*argv) = args;
// declares argv as a pointer to the array args

for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}

return 0;
}
 
J

John Harrison

Robin Sanderson said:
I have just noticed that I posted the wrong version of Programm 3 -
the "** argv" should have been "* argv[]", and this is corrected below
- although this does not alter whether or not it compiles.

This may be a(nother) daft question, but what is it that makes the
difference between the use of "char * argv[3]" in Program 2 and "char
* argv[]" in Program 3?

The first is an array, the second is a pointer. Even though you say char*
argv[], it is a pointer. Using [] in a function parameter is just another
way of declaring a pointer (in other words [] is a lie, it looks like an
array but it isn't). There is no way to have an array as a function
parameter. So the real difference is that in one case argv is a function
parameter (no arrays allowed) and in the second case argv is a local
variable (arrays are allowed).
Is it possible to declare argv as a pointer
in Program 2 (so it can be used in an identical way as in the other
programs)?

Sure, one way would be

int argc=3;
char * argv_array[3];
char ** argv = argv_array;

argv[0] = "program_name";
argv[1] = "argument_1";
argv[2] = "argument_2";

john
 
J

JKop

Robin Sanderson posted:

//Program 2
#include <iostream>
using std:: cout; using std::endl;

int main()
{
int i;

int argc=3;
char * argv[3];

argv[0] = "program_name";
argv[1] = "argument_1";
argv[2] = "argument_2";

for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}

return 0;
}


argv is of type char* const. You can't change it's value.




char * argv[3];

char * pCurrent = argv;

pCurrent++;



-JKop
 
J

JKop

JKop posted:
Robin Sanderson posted:

//Program 2
#include <iostream>
using std:: cout; using std::endl;

int main()
{
int i;

int argc=3;
char * argv[3];

argv[0] = "program_name";
argv[1] = "argument_1";
argv[2] = "argument_2";

for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl; argv++; }

return 0;
}


argv is of type char* const. You can't change it's value.




char * argv[3];

char * pCurrent = argv;

pCurrent++;



OOPS!!!!

char ** pCurrent = argv;



-JKop
 
R

Rolf Magnus

JKop said:
Robin Sanderson posted:

//Program 2
#include <iostream>
using std:: cout; using std::endl;

int main()
{
int i;

int argc=3;
char * argv[3];

argv[0] = "program_name";
argv[1] = "argument_1";
argv[2] = "argument_2";

for(i=0;i<argc;i++)
{
cout << "i="<<i<<"; *argv = " << *argv << endl;
argv++;
}

return 0;
}


argv is of type char* const.

No, it isn't. it's of type array of type char* with 3 elements.
 
R

Robin Sanderson

Thanks Rolf and John for your clear explanations. I have to admit I
still don't understand why Program 2 compiled and ran on .NET, but
otherwise I am starting to get the hang of this C++ pointer-malarkey.

Thanks again,

Robin
 
O

Old Wolf

JKop said:
Robin Sanderson posted:
int main()
{
int i;

int argc=3;
char * argv[3];


argv is of type char* const. You can't change it's value.
No, argv's type is " array[3] of char* ". When used in an expression
like argv++ it is equivalent to &argv[0], which has type " char ** ".
There is no "const" anywhere. argv is a non-modifiable lvalue (which
is a distinct concept from "const"). Another example of a non-modifiable
lvalue is the address of a builtin type; the following code won't
compile for the same reason:
int x;
++ &x;
or
(&x) = 0;
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,797
Messages
2,569,647
Members
45,378
Latest member
danzeev

Latest Threads

Top