2

I have a simple setup as follows (you can also test it here: http://cpp.sh/3yxqj):

// Example program
#include <iostream>
#include <string>

void a (const char c[][2])
{
    std::cout << "func c: " << (sizeof(c)/sizeof(c[0])) << std::endl;
}

int main()
{
    const char c[][2] = {
      {1,2},
      {3,4},
      {5,6},
      {7,8},
      {9,10},
      {11,12},
     };

    std::cout << "main c: " << (sizeof(c)/sizeof(c[0])) << std::endl;

    a(c);

    return 0;
}

The output is:

main c: 6
func c: 4

Where of course 6 is correct and 4 is not. I think I understand why this is happening. The array [][] degenerates (forgive this term) into a pointer (*)[] inside the function. I don't know how to solve this problem though. I need to be able to count rows in multidimensional array after passing it into a function. Can someone please help?

Davidus
  • 23
  • 4
  • 2
    Odd to see a very familiar basic problem with arrays presented with a perfect testcase from a new user! – Lightness Races in Orbit Dec 28 '15 at 01:24
  • The conventional term you're looking for is "decay" (I think "degenerate" is a very good choice but it's too late to change now). – molbdnilo Dec 28 '15 at 01:38
  • 1
    I have been trying to solve this for 3 days :) I come from a non-pointer world, thus I find very shocking that counting elements in an array is such a big deal in C/C++ – Davidus Dec 28 '15 at 01:39
  • 1
    @Davidus: It's not, if you use the proper, modern tools. You are using array technology from the 1960s/1970s. `std::array` gives you a simple `.size()` member that would have seen you finished with your problem in seconds. Which C++ book are you using? – Lightness Races in Orbit Dec 28 '15 at 01:41
  • @LightnessRacesinOrbit: I am not using any book. I am familiar with C-style languages so I code and solve problems as I go using google :) – Davidus Dec 28 '15 at 01:46
  • Well then no wonder it took you three days to find out the worst way to determine an array's size! Seems odd to blame that on C++ as a result. C and C++ are almost _completely_ different. The best way to learn C++ is with a book and I _strongly_ recommend you get one: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – Lightness Races in Orbit Dec 28 '15 at 01:47
  • @LightnessRacesinOrbit: about std::array - I googled this as well but I don't seem to be able to leave the first dimension blank when using std::array. I have series of arrays which are [N][8] - they all have 8 columns and N rows (known at compile time, but I shouldn't have to specify them explicitly). – Davidus Dec 28 '15 at 01:51
  • @LightnessRacesinOrbit: Thank you for the suggestion. I will start reading. – Davidus Dec 28 '15 at 01:52
  • On balance I don't think that's a good enough reason to eschew it. – Lightness Races in Orbit Dec 28 '15 at 01:53

1 Answers1

3

Have a take the array by reference. That'll prevent the decay.

You'll need to also specify the other array dimension:

void a(const char (&c)[6][2])

You could use a template to make this more reusable:

template <size_t N>
void a(const char (&c)[N][2])

or even the more general:

template <typename T, size_t N>
void a(const T (&c)[N])

Once you're doing this, you might as well lose the sizeof entirely:

template <typename T, size_t N>
size_t a(const T (&c)[N])
{
   return N;
}

Then:

std::cout << "main c: " << (sizeof(c)/sizeof(c[0])) << std::endl;
std::cout << "func c: " << a(c) << std::endl;

// g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
// main c: 6
// func c: 6

(live demo)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Thank you for fast response. Here is another problem: I tried the template approach before, but hit another roadblock. Since I have my code written as a class, the template approach forces me to have implementation of my function in .h file, which for some reason I am not willing to do :) If I have the method prototype in .h and implementation in .cpp, I get a linker error Do you know how to get around that? – Davidus Dec 28 '15 at 01:38
  • @Davidus: That's another question; please post it as such after performing the appropriate prior research! – Lightness Races in Orbit Dec 28 '15 at 01:38
  • Ah heck I'll save you some time. Don't put the implementation in .cpp. It's a template so you can't do that (massively simplifying). Google around for why. – Lightness Races in Orbit Dec 28 '15 at 01:39
  • I know, I googled for many nights, but somehow it makes my blood boil if I don't separate implementation from prototypes :) – Davidus Dec 28 '15 at 01:48
  • @Davidus: You can separate them but not in the way you've done. Research the topic, as I've suggested. Y'know, a C++ book would have explained this to you... – Lightness Races in Orbit Dec 28 '15 at 01:49
  • Thank you for your help. Think or swim and ask questions when in doubt. That has worked for few decades for me :) – Davidus Dec 28 '15 at 02:01