what is the difference between the following two approaches:

#include <iostream> 
using namespace std; 

int main(int argc, char* argv[]) { 
   cout << "argc = " << argc << endl; 
   for(int i = 0; i < argc; i++) 
      cout << "argv[" << i << "] = " << argv[i] << endl; 
   return 0; 
}
#include <iostream> 
using namespace std; 

int main(int argc, char** argv) { 
   cout << "argc = " << argc << endl; 
   for(int i = 0; i < argc; i++) 
      cout << "argv[" << i << "] = " << argv[i] << endl; 
   return 0; 
}

both output the same results, one has a parameter of array of char pointers, the other has a pointer to pointer of character.

char *argv[] and char **argv represent the same type, it's just two ways to say the same thing. Think about how char a[] turns into char *a and apply the same logic.

There's no real difference in how the symbol is treated other than the fact that the compiler would allow you to modify argv in the second example. (Not that modifying argv is a good idea.)

The first example should complain if you tried to do argv++ but the second example should happily let you do it -- even though its a bad idea.

>other than the fact that the compiler would
>allow you to modify argv in the second example
Which you could do in the first example as well. It's guaranteed that both argc and argv are modifiable, and all of the strings contained within argv are modifiable as well. The difference between char **argv and char *argv[] is 100% syntactic sugar with no semantic difference.

>The first example should complain if you tried to do argv++
So can you prove this, or are you just trying to act smart with the hope that nobody will call you on it? Let's see two complete sample programs where the only difference is that one program uses char **argv and the other uses char *argv[] . Then let's see a list of compilers that produce a diagnostic with one of the programs but not the other. And be sure to post the actual diagnostic messages as well.

I apologize, it would appear in that context that you can in fact do an argv++.

I expected a compiler error similar to the one this code generates:

int main(int argc, char * argv[])
{
	argv++;
	int foo[] = {1,2,3};
	foo++;

Where I get the following error on the foo++ line:

error C2105: '++' needs l-value

That's different. foo can't be incremented because it's an array and that's not a compatible operation for an array type. argv is actually a pointer, so pointer arithmetic works just fine. You can better simulate the behavior of argv like this:

#include <iostream>

void func ( char *foo[] )
{
  while ( *foo != 0 )
    std::cout<< *foo++ <<'\n';
}

int main()
{
  char *foo[] = {"this", "is", "a", "test", 0};

  func ( foo );
}

I think that extra pointer is potentially confusing, so here's the same code with an array of int instead of an array of pointers to char:

#include <iostream>

void func ( int foo[] )
{
  while ( *foo != 0 )
    std::cout<< *foo++ <<'\n';
}

int main()
{
  int foo[] = {1, 2, 3, 4, 0};

  func ( foo );
}

You see, even if you use array notation for the first dimension of an array parameter, it's still a pointer. The following definition of func is completely identical:

void func ( int *foo )
{
  while ( *foo != 0 )
    std::cout<< *foo++ <<'\n';
}

Arrays as function parameters are one of the many places where an array name is converted to a pointer to the first element of the array. This rule is also why foo[i] and *(foo + i) are equivalent. foo[i] is actually syntactic sugar as well; it's converted by the compiler to the equivalent pointer offset calculation.

This question has already been answered. Start a new discussion instead.