# Double pointer to argv

## Recommended Posts

TheBinaryMan    138
Hello. Im still not comfortable working with pointers when arrays and strings are involved, so hopefully clarification will help. If I have the following code:
char **p_argv;int main(int argc, char *argv[]){    p_argv = argv;    for(int i=0;i<argc;i++)        cout << (*p_argv[i]) << endl;}

If I use "(*p_argv[i])" to dereference one level, I get the beginning char for each string in argv. How do I access the rest of the chars for each of the strings?

##### Share on other sites
KulSeran    3267
There are a couple way about doing this. Since you are using C++, I'd say go the "safe" route below. But if you want to do this the classic C way to learn how C style strings are used, go the "unsafe" way.

#include <string>#include <iostream>#include <cstring>int main(int argc, char *argv[]){    // The safe way    for(int i=0; i < argc; ++i)    {       const std::string arg = argv[i];       std::cout << arg << std::endl;              //this       const std::string::size_type length = arg.length();       for( int j = 0; j < length; ++j )          std::cout << arg[j] << std::endl;       //or better yet, this:       for( std::string::const_iterator itr = arg.begin(); itr != arg.end(); ++itr )          std::cout << *itr << std::endl;    }    // The unsafe way    for(int i=0; i < argc; ++i)    {       const char *arg = argv[i];       std::cout << arg << std::endl;       const size_t length = strlen(arg);       for( int j = 0; j < length; ++j )          std::cout << arg[j] << std::endl;    }}

I say one is safe and the other isn't because direct pointer manipulation can quickly lead to bugs if you are unsure what you are doing. Try not to use C style strings in C++ code. Use std::string whereever you can.

##### Share on other sites
aeroz    171
Quote:
 Original post by TheBinaryManIf I use "(*p_argv[i])" to dereference one level, I get the beginning char for each string in argv. How do I access the rest of the chars for each of the strings?

You are "dereferencing" two levels. one with x[i] and one with *x.

x[0] is the same as *x

(*p_argv[i]) is the same as p_argv[i][0]

Just write p_argv[i] to get the whole string

##### Share on other sites
Zahlman    1682
char* argv[] is a variable named argv of type char* [].*

What is that type? It's an array (hence []) of char*.

So, argv[i] gives us element #i of the array. Each element is a char*.

Supplying a char* to std::cout::operator<< prints the pointed-at string.

Now, how about *argv[i]? That is taking argv[i], which is a char*, and dereferencing it, using the '*'. Dereferencing a char* gives us a char - the one that the pointer is pointing at.

When a char* is used to represent a string, it points at the beginning of the string (which is assumed to just run until the next zero byte). Thus, dereferencing the char* yields the beginning character of the string.

Supplying a char to std::cout::operator<< prints the character.

* This is actually a lie. Because the array size isn't known before we run the program, we can't specify it, and therefore this isn't really an array. The type is actually char**. But we will be using it the same way.

Incidentally, "the array size isn't known before we run the program" is why we need the argc parameter. :)

As for KulSeran's advice, I'd take it a little further:

#include <vector>#include <string>#include <algorithm>#include <iterator>#include <iostream>#include <ostream>int main(int argc, char* argv[]) {  // First, since both arrays and C-style strings cause problems, let's  // replace both with real first-class types:  std::vector<std::string> args(argv, argv + argc);  // Let's use the standard library to display the strings on separate lines:  std::copy(args.begin(), args.end(), std::ostream_iterator<std::string>(std::cout, "\n"));  // And just for show: we can, of course, feed the input directly to std::copy:  std::copy(argv, argv + argc, std::ostream_iterator<char*>(std::cout, "\n"));}

C++ is a very different language from C. :)

##### Share on other sites
TheBinaryMan    138
Thanks for the clarification Zahlman, makes sense now.