2
#include<iostream>
using namespace std;

int main()
{
    char a[2][2] = {"A","B"};
    cout << a << endl;
}

Since a[] stores the address of the first index it have to print A and B. But it is printing some address. What is the wrong in the program to print A and B ?

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
Robin Mandela
  • 117
  • 1
  • 3
  • 11

2 Answers2

5

The problem lies in the overload of operator<< for std::ostream. The specialization that prints ascii characters uses const char *, and you are trying to print char[][], which will decay into a type that's going to be printed as a "generic pointer" (void const * to be precise) - char(*)[2], or "a pointer to two-element array of char (thanks to @Wintermute for that).

std::array<std::string, 2> a { "A", "B" }; is probably the most idiomatic solution here.

If you don't want to modify the contents, std::array<const char*, 2> will also do just fine; const char* is the type of string literals. If you store them that way, you're actually storing the addresses to where the compiler puts them when building the binary. This memory isn't modifiable by you, that's why you have to use const. The string variant copies the data, when that place of code is encountered, to a part of memory you have write access to.

Of course, when you choose the proper way, the actual printing needs to be changed, too!

for (auto const& str : a) {
    cout << str << endl;
}

Oh and also, you probably don't want to use using namespace std;.

Community
  • 1
  • 1
Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
  • 1
    `char*` is printed as a string, not as a pointer. Nor does the array decay to `char*`; it is not one-dimensional. – Wintermute Jan 13 '15 at 14:33
  • @Wintermute ah my bad. I'll add the explanation; I've overlooked the real problem. However, I still think that the decay *will* in fact happen; perhaps to `char[]*` instead – Bartek Banachewicz Jan 13 '15 at 14:34
  • 1
    It decays to `char(*)[2]`, which is a pointer to an array of two characters. The ultimately used `operator<<` is the one for `void const *`, because `char(*)[2]` is convertible to it but not to `char const *`. – Wintermute Jan 13 '15 at 14:37
  • @Wintermute there. I always mistake `[]` and `[n]` :S. Thanks for your comments! – Bartek Banachewicz Jan 13 '15 at 14:38
  • #include using namespace std; int main() { char a[]="hii"; cout< – Robin Mandela Jan 13 '15 at 14:38
  • @RobinMandela that's because `char[]` decays to `char*`, which *will indeed use* the "stringified" overload. That's not the case in array-of-arrays decay, as noted above. – Bartek Banachewicz Jan 13 '15 at 14:39
  • #include using namespace std; int main() { const char *a[2][2]={"A","B"}; cout< – Robin Mandela Jan 13 '15 at 14:42
  • 1
    This time you have an array of an array of pointers. a decays to (hold on tight) `char *(*)[2]`, which is a pointer to an array of two pointers to char. This is still convertible to `void const *` but not to `char const *`. – Wintermute Jan 13 '15 at 14:45
2

In C++, just make yourself a favor and use some convenient container classes like a proper combination of std::vector and std::string: std::vector<std::string>.

std::vector<std::string> a{"A", "B"};

is much simpler and (easier to extend, e.g. if you want to dynamically add more strings to the vector) than the raw-C-like solution.

Mr.C64
  • 41,637
  • 14
  • 86
  • 162