4

I'm trying to obtain a begin and one off the end pointer for a array of C-style strings (an array of pointers to char). Why can't I call the begin and end function in order to obtain them?

#include <iostream>
#include <iterator>

int main(int argc,char *argv[])
{
  char **first=std::begin(argv),**last=std::end(argv);
}

The compiler says that there's no matching function for my call to begin(char**&)

4
  • 2
    char *argv[] is adjusted to a pointer, char **argv, it only looks like an array Commented Aug 21, 2015 at 15:23
  • @PiotrSkotnicki aren't all array converted to pointers? isn't that the whole point of conversion,to be able to pass "an array" to a function? so I0m passing a pointer to the begin and end function, shouldn't it work?? Commented Aug 21, 2015 at 15:25
  • 2
    @Luca You can pass arrays to functions, via reference or pointer to array, just not by value. There is a difference between passing a pointer and an array, and std::begin needs an actual array. Commented Aug 21, 2015 at 15:27
  • Arrays are not converted to poiners. They are decayed to pointers, in approriate context. And you can easily pass an array to a function by wrapping it up in the struct. Commented Aug 21, 2015 at 15:38

2 Answers 2

6

The functions are applied to arrays. As for the parameter argv then it actually has type char ** because arrays passed by value are converted to pointers to their first elements and parameters are adjusted also to pointers.

You could write simply

#include <iostream>
#include <iterator>

int main(int argc,char *argv[])
{
   auto first = arg, last = argv + argc;
}

You could use the functions std::begin and std::end if your function declares the corresponding parameter as reference to array. For example

int MyMain( char * ( &argv )[10] )
{
   auto first = std::begin( argv ), last = std::end( argv );
}

Nevertheless it is the same if to write

   auto first = argv, last = argv + 10;

Here is how the functions are defined in the C++ Standard

template <class T, size_t N> T* begin(T (&array)[N]);
4 Returns: array.

template <class T, size_t N> T* end(T (&array)[N]);
5 Returns: array + N.
Sign up to request clarification or add additional context in comments.

Comments

1

The problem that the compiler faces, is that it has no way to guess the size of argv, because it is not an array but a mere pointer.

Arrays can always be used as pointers, because an array can decay to a pointer to its first element. But the inverse is false! You can access the elements of an array through the array or through a pointer exactly the same, but the pointer and the array are not the same:

int a[5];
int *p = a; // p[i] and a[i] are now the same
size_t s = sizeof(a); // s is 5 * sizeof(int) 20 on common (32 bits) architectures
size_t s2 = sizeof(p);  // s2 is just sizeof(int *) 4 on 32 bits architecture

The convention says that argv has argc elements (and that argv[argc] is a null pointer). But std::begin and std::end do not make use of that convention. So do it by hand as a nice programmer:

#include <iostream>
#include <iterator>

int main(int argc,char *argv[])
{
  char **first=argv,**last=argv + argc;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.