0

I'm just curious what is the reason for the following error: I'm trying to determine the size of an integer array.

When I find the size of array in main function, this code returns correctly:

 int program[12] = { 1007, 1008, 2007, 3008, 2109, 1109, 4300, 0, 0, 0, -99999 };
 cout<<sizeof(program)/sizeof(program[0])<<"\n";

But if I pass program to a function by value, it always return 2:

void Sipmletron::load(int program[])
{
    int length=sizeof(program)/sizeof(program[0])
    std::cout<<length<<"\n";
    memory= new int[length];
}
Dzung Nguyen
  • 3,794
  • 9
  • 48
  • 86

4 Answers4

6

You cannot pass arrays by value. The argument is passed as a pointer to the first element of the array, so you are in effect calculating sizeof(int*) / sizeof(int).

Jon
  • 428,835
  • 81
  • 738
  • 806
  • +1: although i agree with your answer, isn't the size of a pointer and an int the same? So my thought was that length would be 1 instead of 2? – masotann Jun 06 '13 at 23:14
  • it should be mentionned the value 2 means pointers are twice the size of integers on the OP's platform, probably 64 bits (8) for int *, and 32 bits (4) for int. – SirDarius Jun 06 '13 at 23:15
  • 2
    @Calpis: We can probably guess that the compiler used targets a 64-bit environment. But if I 'm not mistaken, theoretically it's also possible for `int` to be just 16 bits. – Jon Jun 06 '13 at 23:15
  • That's correct, the OS is 64 bits. Thanks for the clarification! – Dzung Nguyen Jun 06 '13 at 23:17
2

When an array is passed in C++ (and in C), it looses it's size (it's passed as the address of the first element, no matter whether it is int * or int []).

You can use std::array if you are using C++11, which has a size() member function, similar to vector. In almost all other aspects, it is the same as a standard C style array.

Otherwise, you have to pass the size along with the array - or use some marker to indicate the end (looks like you already have that with -99999).

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
1

There are two special-case language rules at play here, both inherited directly from C.

  1. An expression of array type, in most contexts, is implicitly converted to ("decays to") a pointer to the array's first element. The exceptions in C are when the expression is the operand of unary & or sizeof, or when it's a string literal in an initializer used to initialize an array (sub)object. C++ has more exceptions, but none that apply here.

  2. A parameter defined as some_type foo[] is "adjusted" to some_type *foo, so your parameter program is really a pointer, not an array. (This adjustment occurs only for parameter declarations.)

These rules (unfortunately IMHO) work together to make it appear that you're passing an array object by value, and accessing an array inside your function, but in fact it's all pointers.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
0

You could do this with templated member functions if you really wanted to:

    template <size_t N>
    void Sipmletron::load(int (&program)[N])
    {
      size_t length = N;
      std::cout << length << "\n";
      memory = new int[length];
    }

In addition, and even without seeing the rest of your code, I'm feel sure it would be worth your while looking at using a std::vector instead of doing your own memory management using new, with a more idiomatic load(...) that used iterators.

clstrfsck
  • 14,715
  • 4
  • 44
  • 59