0

I'm trying to pass an array as a pointer to a function, but when I do that the function only sees the pointer as an array with 1 variable. Here is my code:

void make3(int* a) {
    int n = sizeof(a) / sizeof(a[0]);
    for (int i = 0; i < n; i++) {a[i] = 3;}
}
int main()
{
    int a[3] = { 0, 1, 2 };
    make3(a);
    int* b = a;
    for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++) {
        cout << *(b + i) << endl;
    }
}

The function make3 only changes the first value of the array to 3, instead of all of them. Is this normal? If not, what am I doing wrong?

  • 1
    `int a[3]` is an array;. `int* a` is a pointer. An array will *decay* to a pointer, but regardless an array is not a pointer. What you are doing wrong is you are not using a `std::vector`. – Eljay Nov 20 '21 at 12:43
  • @Eljay It's supposed to be a simple array, which is why i can't use vector. But thank you! – pink_totoro Nov 20 '21 at 12:46
  • can you explain why you specifically need to pass the array as a pointer and why you cannot afford to pass the size as argument ? – trialNerror Nov 20 '21 at 12:47
  • A pointer is not actually an array. In your example, `make3()` is only passed the address of the first element of the array passed by `main()`. The function has no way in standard C++ to obtain the number of elements in that array. If you need to obtain the size (number of elements) you need to pass it in some way (e.g. as an additional argument) or, as Elijay said, use `std::vector` (which is a data structure with member function, so you can obtain the size). If you can't use `std::vector`, must pass a pointer, but you can't pass the size somehow, there is NO WAY to get the size. – Peter Nov 20 '21 at 12:57
  • Many of the answers and comments suggest `std::vector` which is an excellent replacement. However for these specific use cases (known fixed size) there is also `std::array`. – Chad Nov 20 '21 at 13:47

2 Answers2

3

When you pass an array to a function, it decays to a pointer.

int n = sizeof(a) / sizeof(a[0]);

Gets evaluated to

int n = sizeof(int*) / sizeof(int);

Which is 1 (when sizeof(int*) is 4 - depends on inplementation).

You should pass the array size as an argument instead:

void make3(int* a, int n) {
    for (int i = 0; i < n; i++) {a[i] = 3;}
}

int main()
{
    int a[3] = { 0, 1, 2 };
    make3(a, 3);
    for (int i = 0; i < 3; i++) {
        cout << a[i] << endl;
    }
}

If you can’t add that argument, use std::vector:

#include <vector>

void make3(std::vector<int> &a) {
    for (int i = 0; i < a.size(); i++) {a[i] = 3;}
}

int main()
{
    std::vector<int> a{ 0, 1, 2 };
    make3(a);
    for (int i = 0; i < a.size(); i++) {
        cout << a[i] << endl;
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
3

Is this normal?

Yes.

In C++, an array will decay to a pointer at any opportunity. C++ inherited this convenience behavior from C.

It makes thinking about arrays as-if they were the same as pointers. But they are not.

In C++ a pointer can point to nothing (nullptr), or point to an object, or point to an array of objects. The pointer is oblivious of whether it points to an object or an array of objects.

(Or be dangling, or be uninitialized, or be some arbitrary value. These should be avoided.)

If not, what am I doing wrong?

You are not using std::vector.

Since, in the comments, you say that you cannot use a std::vector, then you'll need to pass in the length of the array as a std::size_t parameter along with a pointer to the array.

But you also say you cannot pass in the length of the array. So then you will need to use an array reference rather than a pointer.

Also, C++17 has std::size(a) which can be used instead of sizeof(a)/sizeof(a[0]).

#include <cstddef>
#include <iostream>

using std::cout;
using std::size_t;

template <size_t N>
void make3(int(&a)[N]) {
    for (size_t i = 0; i < N; ++i) {
        a[i] = 3;
    }
}

int main() {
    int a[3] = { 0, 1, 2 };
    make3(a);
    int* b = a;

    for (size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i) {
        cout << *(b + i) << "\n";
    }
}
Eljay
  • 4,648
  • 3
  • 16
  • 27
  • To be a little bit clearer: a properly initialized non-null pointer always points at an object. Sometimes that object is a single entity, and sometimes it's the first element of an array. (it can also point at an element in the middle of an array, but that's less common). +1. – Pete Becker Nov 20 '21 at 14:09