7

I'm learning C++ these days by myself and I have some problem understanding why this code doesn't compiles using #g++ -std=c++11 source.cpp. Actually it doesn't matter which specific standard I use, it just doesn't compiles.

#include <iostream>
#include <string>
using namespace std;
int print_a(char array[])
{
    for(char c : array)
        cout << c;
    cout << endl;
    return 0;
}
int main(void)
{
    char hello[] {"Hello!"};
    print_a(hello);
    return 0;
}

The error message:

debian@debian:~/Documents$ g++ -std=c++11 source.cpp
source.cpp: In function ‘int print_a(char*)’:
source.cpp:6:15: error: ‘begin’ was not declared in this scope
  for(char c : array)
               ^
source.cpp:6:15: note: suggested alternatives:
In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0,
                 from /usr/include/c++/4.9/string:52,
                 from /usr/include/c++/4.9/bits/locale_classes.h:40,
                 from /usr/include/c++/4.9/bits/ios_base.h:41,
                 from /usr/include/c++/4.9/ios:42,
                 from /usr/include/c++/4.9/ostream:38,
                 from /usr/include/c++/4.9/iostream:39,
                 from source.cpp:1:
/usr/include/c++/4.9/initializer_list:89:5: note:   ‘std::begin’
     begin(initializer_list<_Tp> __ils) noexcept
     ^
/usr/include/c++/4.9/initializer_list:89:5: note:   ‘std::begin’
source.cpp:6:15: error: ‘end’ was not declared in this scope
  for(char c : array)
               ^
source.cpp:6:15: note: suggested alternatives:
In file included from /usr/include/c++/4.9/bits/basic_string.h:42:0,
                 from /usr/include/c++/4.9/string:52,
                 from /usr/include/c++/4.9/bits/locale_classes.h:40,
                 from /usr/include/c++/4.9/bits/ios_base.h:41,
                 from /usr/include/c++/4.9/ios:42,
                 from /usr/include/c++/4.9/ostream:38,
                 from /usr/include/c++/4.9/iostream:39,
                 from source.cpp:1:
/usr/include/c++/4.9/initializer_list:99:5: note:   ‘std::end’
     end(initializer_list<_Tp> __ils) noexcept
     ^
/usr/include/c++/4.9/initializer_list:99:5: note:   ‘std::end’
Davycc
  • 73
  • 1
  • 5

3 Answers3

14

The reason it doesn't compile is that in C++ a function parameter such as char array[] is adjusted to char* array. Your function really looks like

int print_a(char* array)
{
 ....
}

and the range based loops cannot deal with a pointer.

One solution is to pass the array by reference. C++ does not allow you to pass plain arrays by value. For example, this would accept an array of 5 chars:

int print_a(const char (& array)[5])
{
   for(char c : array) cout << c;
   cout << endl;
   return 42;
}

In order to generalise this to arrays of different sizes, you can use a template:

template <std::size_t N>
int print_a(const char (& array)[N])
{
   for(char c : array) cout << c;
   cout << endl;
   return 42;
}

Of course, there are easier ways to print a null-terminated string:

char hello[] {"Hello!"};
cout << hello << endl;

And there are standard library types that make passing string or char buffer objects around easier. For example, std::string, std::vector<char>, std::array<char, N> (where N is a compile time constant.)

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Thank you! I'm just playing with it. It's kind of practice for me. I agree, there is many better ways to do the same but it's the simplest way to find out about range-based loops and array decaying, don't you think?! P.S. Thank you all, guys. I appreciate your help! – Davycc Aug 05 '15 at 06:12
  • 1
    @Davycc It really is type adjustment. Decaying is what happens when you initialize a pointer from an array. – juanchopanza Aug 05 '15 at 06:13
4

Here

int print_a(char array[])
{
    for(char c : array)
        cout << c;
    cout << endl;
    return 0;
}

The array is decayed to a pointer, because when you pass an array be value, what exactly you are doing to pass the pointer to the first element of the array, and range based loops can't work with pointers,hence the error you are getting.

See this for how arrays are decayed and what is the solution.

You need to use pass by reference or pointer.

Community
  • 1
  • 1
Nishant
  • 1,635
  • 1
  • 11
  • 24
4

When you pass the array to the function, it "decays" to a pointer. As in the function really looks like this: int print_a(char *array) {...} The type of loop you are using, called a range loop, cannot handle pointers, which is the source of the error (trying to iterate over a pointer makes no sense).

Either you must pass the array by reference, or just use a regular for loop.

Honestly, if you are using C++ though, use C++. Use std::string, or std::vector.

Iowa15
  • 3,027
  • 6
  • 28
  • 35