Why Do You Have To Use Different Pointers For Arrays?

So when if you want to change the values themselves for example in an array (just for example) this is valid;


1
2
3
4
5
6
7

    void test(int* test)
    {
        test[0] += 10; 
    }

int bob[] {1, 3, 5};


If you did that bob[0] would not equal 11. All well and good right?


Now if you do this?

1
2
int sally = 33;
test(sallay);


This wouldn't work at all you actually have to use

1
2
3
4
 void test(int& test)
    {
        test += 10; 
    }


Can someone explain scientifically how the memory addresses etc. are working here? I don't understand why you need to use & the reference operator if it's not an array? Why wouldn't that still work?
Well, actually, you don't. For your second example, this is what you could do:

1
2
3
void test(int* test) {
    *test += 10;
}


Now, the thing to realize is that the [] operator is simply a shorthand way of derefencing a pointer, plus a certain offset. This is what it does:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int array[10];  // array of size 10
array[5] = 6; // set 6th value to 6
*(array + 5) = 6; // does same thing as line 2

// This means that the following functions are equal:
void test1(int* test) {
    *test += 5;
}

void test2(int* test) {
    *(test + 0) += 5;
}

void test3(int* test) {
    test[0] += 5;
}


Hope this helps!


EDIT:
A few things in your examples:
bob[0] WOULD equal 11 (if you did your initializer list properly), because you have passed a pointer to bob, meaning that you are directly editing its values. This is, incidentally, the reason that your sally example doesn't work: Sally isn't a pointer to memory, it is actually memory itself. This means that the program will try to edit the memory located at 0x21 (33) in memory, which is almost certainly out of bounds and will cause a segmentation violation. The following would work, however:
1
2
3
4
5
6
int sally = 33;
// Make a pointer that points to the location in memory held by sally
int* sallyptr = &sally;
test (sallyptr); // this will work now
test (&sally); // this does the same thing
cout << sally << endl // => 53 (33 + 10 + 10) 
Last edited on
When you pass an array to your function, test(), you are actually passing the address of the first element in the array. You can't pass an int to the function, only the address of (a pointer to) an int. You could actually pass the address of your int, sally, to test() like so:

 
test(&sally);


the '&' operator in this context gets the address of the variable 'sally'. In a function definition however, it means that the function takes that variable by reference. These are two seperate things and a lot of people are tripped up by the fact that they use the same symbol '&'.

Note that if you do pass the address of a single variable to a function, the proper way to dereference the pointer is

 
*test += 10;


although this

 
test[0] += 10;


would also work.

"test[n]", where n is any int, essentially means "the variable at the address passed into the function, plus the size of "n" ints. If you have passed in the address of an array this allows you to access any element in the array by looping from 0 to n, but if you have passed the address of a single int variable then you cannot use this syntax if n is greater than 0.

If you still don't get it, this tutorial probably explains pointers much better than I just did.
http://www.cplusplus.com/doc/tutorial/pointers/
Last edited on
The ampersand & in your case is not the reference operator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int a;

int *pa = &a; // pointer declaration
// * is part of the declaration
// & is the reference operator, takes address of a

*pa = 5; // * is the dereference operator
// now a equals 5

int &ra = a; // reference declaration
// & is part of the declaration
// ra is an alias (different name) for a

ra = 6; // now both a and ra equal 6
a = 16; // now both a and ra equal 16

void func(int *p) // * is part of the declaration of p
{
}

void func(int &r) // & is part of the declaration of r
{
}


So, when * and & are used in between a type and an identifier (a name of a variable for example) then they are part of the declaration.

When they are used for a single variable, they are unary operators.
When they are used in between two variables, they are binary operators.

Type *x == declaration of pointer, * is not operator
*a == dereference operator
a * b == multiplication operator

Type &y == declaration of reference, & is not operator
&a == reference (address-of) operator
a & b == "bitwise AND" operator


Now with regards to your question... in C++ arrays decay to pointers. This means that when you use an array's name, it actually becomes a pointer to the first element in the array. This is why code like this works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>

void func_a(int *p)
{
    p[0] = 100;
}

void func_b(int arr[3])
{
    arr[1] = 200;
}

void func_c(int arr[])
{
    arr[2] = 300;
}

void func_d(int arr[291])
{
    arr[3] = 400;
}

int main()
{
    int a[4];

    func_a(a); // surprise, works!
    func_b(a); // works...
    func_c(a); // also works
    func_d(a); // also works

    for (int i=0; i < 4; ++i)
        std::cout << a[i] << ' ';

    std::cout << std::endl;
}


It may seem odd that all these functions work, until you remember that in all cases the arr parameter declaration is just syntactic sugar: in reality it's always a pointer parameter, like p.

Of course, the same thing doesn't happen you don't use arrays.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

void func(int *p) // pointer parameter declaration
{
    *p = 123; // dereference operator
}

int main()
{
    int i=90;

    func(&i); // reference (address-of) operator
    std::cout << i << std::endl;
}

Topic archived. No new replies allowed.