What is the meaning of "argv + argc"?

Viewed 591

I'm writing a program that accepts command line arguments and prints them out in alphanumerically sorted order with a custom comparator.

Along the way I got stuck with inserting the command-line arguments in the std::set container. Reviewed some similar code online and found something like:

std::set<char*, decltype(customComparator)> args (argv, argv+argc, customComparator)

What does the argv + argc argument mean/do?

When I tried inserting the cmd argument like:

std::set<char*, decltype(customComparator)> args (argv, customComparator)

There's a red squiggly line on the argv argument.

3 Answers

What is the meaning of "argv + argc"?

argv + argc is a pointer that points to the end of the last command line argument(or to the null shown in the diagram below). This is explained below(both graphically and in text form).

The diagram is shown for argc = 5 :

argv + argc

Explanation

Lets consider the declaration:

int main (int argc, char *argv[])

In the above declaration, the type of the second parameter named argv is actually a char**. That is, argv is a pointer to a pointer to a char. This is because a char* [] decays to a char** due to type decay.

In other words, argv is a pointer that points to the first element of an array with elements of type char*. Moreover, each element argv[i] of the array(with elements of type char*) itself point to a character which is the start of a null terminated character string. That is, each element argv[i] points to the first element of an array with elements of type char.

The code you're showing uses the iterator based constructor, which receives a begin iterator, and a past the end iterator.

The thing is, a pointer is also considered an iterator by the STL. The ++ptr operator works, as well as ptr != end_ptr and *ptr.

So, if you want to construct an STL container from a C-style collection of objects, it's very well possible to do so. argv is the beginning of all the args value(s), and argv[argc - 1] is the end. To get a pointer past the end, simply do argv + argc.

  1. This overload of the std::set constructor accepts two iterators and a comparator. The two iterators should define a half-open range. The second iterator points to the end of the range, which for many kinds of ranges, is the one past the last element.
  2. A pointer is an iterator.
  3. If argv points to the first element of an array, and argc is an integer, then argv + argc points to argcth element of the same array (starting from zero).
  4. Since there are exactly argc meaningful elements in the argv array, argv + argc points one past the last meaningful element of the array. (There happens to be another element there, bit it is a null pointer and we are not interested in it).

All in all, the range [argv, argv + argc) is exactly the kind of half-open range standard library expects in lots of places.

Related