0

My for loop (for debugging) for a capitalism simulator I'm making is not working, as it is exiting at ix=0 (it only executes the loop body once). I also believe it is syntactially correct (from other questions).

Here is my code (I left out the variables):

void print_things(String2Double b, String2Double up_cost, String2Double tFinish, string* bNames) {
    // Just for debugging!
    for (int ix=0;ix<(sizeof(bNames)/sizeof(bNames[0]));ix++) {
        cout << "Count of business " << bNames[ix] << ": " << b[bNames[ix]] << endl;
        cout << "Upgrade cost for " << bNames[ix] << ": " << up_cost[bNames[ix]] << endl;
        cout << "Time to finish for " << bNames[ix] << ": " << tFinish[bNames[ix]] << endl;
        cout << ix << endl;
    }
}

I also had it print the size of bNames[], which is 9 and it only printed ix=0, and I suspected something must be wrong.

Thank you!

  • Welcome to the club of C/C++ most frequently asked questions. – barak manos May 23 '15 at 06:05
  • Why not replace `(sizeof(bNames)/sizeof(bNames[0]))` with `9`? – asimes May 23 '15 at 06:08
  • Since none of the answers below have mentioned it, the phenomenon is known as "**array decaying to pointer**". You might want to look it up on your favorite search engine (Yahoo, DuckDuckGo, StartPage, IxQuick, etc). – barak manos May 23 '15 at 06:11

2 Answers2

1

here bNames is a pointer, not an array.

Xiaotian Pei
  • 3,210
  • 21
  • 40
1

The expression

(sizeof(bNames)/sizeof(bNames[0]))

is not working as you think it should.

That part probably was copied by you without understanding because it's only valid for an array, not for a pointer. Also declaring the parameter as bNames[] in the function wouldn't work either.

You need to pass explicitly the number of elements when using a pointer.

A better approach in C++ would be using an std::vector (but it's strongly suggested you first understand how it works).

Edit

You can only pass array references (not arrays) in C++ if you know the size at compile time, using as syntax:

void print_i10(int (&a)[10]) {
    // `a` here is a reference to an array of 10 integers
}

It's also possible to pass arrays to function templates, having the template infer the array size at compile time; for example:

template<typename T, int N>
void print(const char *format, const T (&a)[N]) {
    printf("[");
    for (int i=0; i<N; i++) {
        if (i) printf(", ");
        printf(format, a[i]);
    }
    printf("]\n");
}

int main(int argc, const char *argv[]) {
    int ia[10] = {1,2,3,4,5,6,7,8,9,10};
    const char *sa[] = {"this", "that", "hmmm..."};

    print("%i", ia);
    print("'%s'", sa);

    return 0;
}

but this means that for each element type and element size you will get a distinct copy of the print function in your program (normally a bad idea).

6502
  • 112,025
  • 15
  • 165
  • 265
  • I _am_ passing in an **array**, and I used that to print out the size. Also the array _is_ not a pointer, it just has unspecified length. –  May 23 '15 at 06:29
  • 2
    You cannot pass an array to a regular function in C/C++. When passing an array the argument decays into a pointer to the first element. – 6502 May 23 '15 at 06:37
  • Then how _do_ I prevent array decay? I've searched it up but there is no straightforward solution. –  May 23 '15 at 06:46
  • 2
    You really cannot prevent it. If you're using C++ you should learn to use containers like `std::vector` that allow you to query their size, not raw pointers. – Retired Ninja May 23 '15 at 06:49
  • @AnirudhBalaji: see edit for some more of the truth about array parameters in C++. Until you get enough understanding of C++ however it's much better to just use `std::vector` instead (and once you'll have enough understanding you'll see that using `std::vector` is better 99% of the times). – 6502 May 23 '15 at 07:08