C++ Pass an Array by Reference

Passing an array by reference in C?

In C arrays are passed as a pointer to the first element. They are the only element that is not really passed by value (the pointer is passed by value, but the array is not copied). That allows the called function to modify the contents.

void reset( int *array, int size) {
memset(array,0,size * sizeof(*array));
}
int main()
{
int array[10];
reset( array, 10 ); // sets all elements to 0
}

Now, if what you want is changing the array itself (number of elements...) you cannot do it with stack or global arrays, only with dynamically allocated memory in the heap. In that case, if you want to change the pointer you must pass a pointer to it:

void resize( int **p, int size ) {
free( *p );
*p = malloc( size * sizeof(int) );
}
int main() {
int *p = malloc( 10 * sizeof(int) );
resize( &p, 20 );
}

In the question edit you ask specifically about passing an array of structs. You have two solutions there: declare a typedef, or make explicit that you are passing an struct:

struct Coordinate {
int x;
int y;
};
void f( struct Coordinate coordinates[], int size );
typedef struct Coordinate Coordinate; // generate a type alias 'Coordinate' that is equivalent to struct Coordinate
void g( Coordinate coordinates[], int size ); // uses typedef'ed Coordinate

You can typedef the type as you declare it (and it is a common idiom in C):

typedef struct Coordinate {
int x;
int y;
} Coordinate;

Passing an Array by reference in C

This is caused by the fact that arrays tend to decay into pointers.

int a[] = { 1, 2, 3 };
int* p = a; // valid: p is now the address of a[0]
a = p; // NOT valid.

printf("a = %p\n", a);
printf("p = %p\n", p); // prints same address as a

a and p will print the same value.

Contrary to what others have said, a is not a pointer, it can simply decay to one. http://c-faq.com/aryptr/aryptrequiv.html

In your first function() what gets passed is the address of the array's first element, and the function body dereferences that. Infact, the compiler is treating the function prototype as this:

void function(int* array /*you wrote int array[]*/){
array[0] = 4;
array[1] = 5;
array[2] = 6;
}

function(&array[0]);

This has to happen because you said "array of unknown size" (int array[]). The compiler could not guarantee to deduce the amount of stack required to pass by value, so it decays to a pointer.

---- Edit ----

Lets combine both your examples and use more distinctive names to make things clearer.

#include <stdio.h>

void func1(int dynArray[]) {
printf("func1: dynArray = %p, &dynArray[0] = %p, dynArray[0] = %d\n",
dynArray, &dynArray[0], dynArray[0]);
}

void func2(int* intPtr) {
printf("func2: intPtr = %p, &intPtr[0] = %p, intPtr[0] = %d\n",
intPtr, &intPtr[0], intPtr[0]);
}

void func3(int intVal) {
printf("func3: intVal = %d, &intValue = %p\n",
intVal, &intVal);
}

int main() {
int mainArray[3] = { 1, 2, 3 };
int mainInt = 10;

printf("mainArray = %p, &mainArray[0] = %p, mainArray[0] = %d\n",
mainArray, &mainArray, mainArray[0]);
func1(mainArray);
func2(mainArray);

printf("mainInt = %d, &mainInt = %p\n",
mainInt, &mainInt);
func3(mainInt);

return 0;
}

Live demo at ideone: http://ideone.com/P8C1f4

mainArray = 0xbf806ad4, &mainArray[0] = 0xbf806ad4, mainArray[0] = 1
func1: dynArray = 0xbf806ad4, &dynArray[0] = 0xbf806ad4, dynArray[0] = 1
func2: intPtr = 0xbf806ad4, &intPtr[0] = 0xbf806ad4, intPtr[0] = 1

mainInt = 10, &mainInt = 0xbf806acc
func3: intVal = 10, &intValue = 0xbf806ad0

In func1 and func2 "dynArray" and "intPtr" are local variables, but they are pointer variables into which they receive the address of "mainArray" from main.

This behavior is specific to arrays. If you were to put the array inside a struct, then you would be able to pass it by value.

Pass Array by Reference in C

Arrays are always passed by reference in C. The name of the array is pointer to the first element of it. So, you just do this :-

void function (int arr[]){
// Some Code.....
}
int main(){
// Some Code...
int name[5];
function(name);
// Some Code...
}

And that would work, you can modify the values of elements in the array and the changes would be reflected in the calling function.

Edit: You know that you have to add a semi-colon after your for loop? Otherwise the next one line will also be iterated. See -

Corrected Code
and
Output

To pass an array by reference in C

int *arr[] is an array of pointers. Or rather it's a pointer to a pointer (it's really int **arr).

To pass a pointer to an array (which almost never is needed) you need e.g. int (*arr) [6]. And yes, the size of the array is then mandatory (variable-length arrays are valid).

But as I said, passning pointers to arrays is almost never needed, because arrays naturally decays to pointers (to their first element).

And as an argument declaration int arr[] is equal to int *arr.

That is, with

void merge(int arr[], int l, int m, int r) 

you already pass the array by "reference".

How do you pass an array by reference from python to a C++ function using CTypes?

You are returning array_type. That’s a type, not an instance of the type. The instance is your array_type(*numbers) passed to the function, but it is not preserved. Assign it to a variable and return that, or better yet convert it back to a Python list as shown below:

test.cpp

#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif

extern "C" API void our_function(double * numbers) {
numbers[0] += 1;
numbers[1] += 1;
numbers[2] += 1;
}

test.py

import ctypes

_sum = ctypes.CDLL('./test')
_sum.our_function.argtypes = ctypes.POINTER(ctypes.c_double),

def our_function(numbers):
array_type = ctypes.c_double * 3 # equiv. to C double[3] type
arr = array_type(*numbers) # equiv. to double arr[3] = {...} instance
_sum.our_function(arr) # pointer to array passed to function and modified
return list(arr) # extract Python floats from ctypes-wrapped array

z = our_function([0, 1, 2])
print(z)

Output:

[1.0, 2.0, 3.0]

c++: passing arrays by reference

Your function is declared correctly, but you are not passing the array to it correctly.

func(*str); first decays the array to a pointer to the 1st element, and then deferences that pointer, thus passing just the 1st character to func(). But there is no func(char) function defined, so this is an error.

func(&str); takes the address of the array, thus passing a pointer to the array, not a reference to it. But there is no func(char(*)[len]) function defined, so this is also an error.

To pass str by reference, you need to simply pass str as-is without * or &:

func(str);

This is no different than passing a reference to a variable of any other type, eg:

void func(int &value);

int i;
func(i);

On a side note: printf(str); is dangerous, since you don't know if str contains any % characters in it. A safer call would be either:

printf("%s", str);

Or:

puts(str);

But those only work if str is null-terminated (which it is in your case). Even safer would be:

printf("%.s", (int)len, str);

Which doesn't require a null terminator.

C pass array by value vs pass array by reference

In C passing by reference means passing an object indirectly through a pointer to it. If you will pass an object directly to a function then the function will deal with a copy of the value of the object.

Compare two function calls in this demonstrative program.

#include <stdio.h>

void f( int x )
{
x = 10;
}

void g( int *x )
{
*x = 10;
}


int main(void)
{
int x = 0;

printf( "Before call f: x = %d\n", x );

f( x );

printf( "After call f: x = %d\n", x );

putchar( '\n' );

printf( "Before call g: x = %d\n", x );

g( &x );

printf( "After call g: x = %d\n", x );

return 0;
}

The program output is

Before call f: x = 0
After call f: x = 0

Before call g: x = 0
After call g: x = 10

That is we passed to the function f the object x directly. So the function deals with a copy of the object x. Changing the copy does not influence on the original object x declared in main.

As for the function g then it got an access to the object x indirectly through a pointer to it. So changing the pointed object we changed the object x declared in main.

As for arrays then when an array is passed to a function it is implicitly converted to pointer to its first element. So the function in fact gets elements of the array by reference through this pointer. Using the pointer and the pointer arithmetic we can change any element of the array.

This function declaration

void set_array(int array[4]);

is equivalent to the following declaration

void set_array(int array[]);

and the both declarations are adjusted by the compiler to the declaration

void set_array(int *array);

So the function deals with a pointer - the pointer to the first element of the array used as an argument of the function call.

The call of the function set_array in your program

set_array(b);

is equivalent to the following call

set_array( &b[0] );

because arrays used in expressions as for example as a function argument expression are implicitly converted to pointers to their first elements.



Related Topics



Leave a reply



Submit