int main(int argc, const char** argv) {
std::cout << "Hello" << std::endl;
char arr2d[][4] = {"ABC", "DEF"};
for (char *i : arr2d)
{
std::cout << i << std::endl;
}
In here, I evaluate the job of forrange as this: "For each character array in arr2d
, print it it to console". And this works, so, my understanding, at least, should be correct. The output to the above code snippet is,
muyustan@mint:~/Desktop/C_Files/oop$ g++ main.cpp -o main && ./main
Hello
ABC
DEF
as expected.
However, if I try this one,
int main(int argc, const char** argv) {
std::cout << "Hello" << std::endl;
char arr2d[][4] = {"ABC", "DEF"};
for (const char *i : argv)
{
std::cout << i << std::endl;
}
First the IDE warns me with,
this range-based 'for' statement requires a suitable "begin" function and none was found
And if I try to compile, I get:
muyustan@mint:~/Desktop/C_Files/oop$ g++ main.cpp -o main && ./main
main.cpp: In function ‘int main(int, const char**)’:
main.cpp:30:26: error: ‘begin’ was not declared in this scope
for (const char *i : argv)
^~~~
main.cpp:30:26: note: suggested alternative:
In file included from /usr/include/c++/7/string:51:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:1:
/usr/include/c++/7/bits/range_access.h:105:37: note: ‘std::begin’
template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
^~~~~
main.cpp:30:26: error: ‘end’ was not declared in this scope
for (const char *i : argv)
^~~~
main.cpp:30:26: note: suggested alternative:
In file included from /usr/include/c++/7/string:51:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from main.cpp:1:
/usr/include/c++/7/bits/range_access.h:107:37: note: ‘std::end’
template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
So, why argv
behaves differently than my arr2d[][4]
? Aren't both of them pointers of char pointers(char arrays or strings(?)) ?
And if something wrong with my understanding, what should be the structre of printing ingreditens of argv
with a forrange?
They behave differently because they have different types. This is confusing for beginners, but:
char **
is a pointer to pointer to char
. In fact, in the case of argv
, it is pointing to a sequence of pointers, each pointing to a nul-terminated string (which are sequences of characters).
The problem iterating those is that the size of those sequences is not known. The compilers cannot know argc
is related to the first sequence mentioned above.
However:
char arr2d[][4] = {"ABC", "DEF"};
resolves to the type:
char [2][4]
Which is an array of arrays of char
. In this case, the size is known (2
), so you can iterate over it.
Finally, the compiler complains about std::begin
because the range-based for loop is transformed into different equivalent code which uses std::begin
etc. to do the iteration.