How can I assign a different address to an array? - c++

I want to pass an array to a function, then point that array variable to a new address altogether within said function.
I realize that arrays behave as pointers to the adress of their first element when passed to a function, so why the heck won't the address change for my array variable in main?
#include <iostream>
using namespace std;
void passArrayByReference(int * array) { //passing array as. pointer should let us modify it's address, correct?
cout << "Address of array in function is: " << array << endl;
int * localArray = new int [2];
//put some dummy values in our localArray
localArray[0] = 9;
localArray[1] = 9;
array = localArray;
cout << "Address of array in function is now: " << array << endl;
}
int main()
{
int * array = new int [2];
int totalElements = 2;
//put some initial values into our dynamic 1D array
array[0] = 0;
array[1] = 1;
//print our initial values
for(int i = 0; i < totalElements; i++)
cout << array[i] << endl;
cout << "Address of array in main: " << array << endl;
passArrayByReference(array);
cout << "Address of array in main: " << array << endl;
return 0;
}

You are on the right track, but you just need to include the '&' symbol in your function header. The '&' symbol is used to pass an argument by reference, as opposed to by value.
In this case you are passing the address to the first element of your array by reference, meaning that you can modify that address in the function, and the changes will be reflected in your main function.
#include <iostream>
using namespace std;
void passArrayByReference(int * &array) {
cout << "Address of array in function is: " << array << endl;
int * localArray = new int [2];
//put some dummy values in our localArray
localArray[0] = 9;
localArray[1] = 9;
array = localArray;
cout << "Address of array in function is now: " << array << endl;
}
int main()
{
int * array = new int [2];
int totalElements = 2;
//put some initial values into our dynamic 1D array
array[0] = 0;
array[1] = 1;
//print our initial values
for(int i = 0; i < totalElements; i++)
cout << array[i] << endl;
cout << "Address of array in main is: " << array << endl;
passArrayByReference(array);
cout << "Address of array in main is now: " << array << endl;
//now print the values of our 'new' array
cout << "The values of array are now:" << endl;
for(int i = 0; i < totalElements; i++)
cout << array[i] << endl;
return 0;
}

First, you have to pass pointer by pointer or reference to make persistent change to it - that is change original pointer and not only copy of it in function body:
void passArrayByReference(int *&array) {
//...
array = new_address;
std::cout << "Address of array in function is now: " << array << std::endl;
}
// and here it is the same
And second you should assign valid address new_address and take care of memory that array referenced just before it entered the function, to avoid memory leak.

Pointers are variables as well.
That's why you need to pass array as a reference to passArrayByReference so you don't just modify the copy of it.
void passArrayByReference(int *&array)

Related

Set array dimension at runtime

I have a struct, which, depending on user inputs at runtime, will either require a 1D array or a 3D array. It will never need both. Right now, I have it set up like in the sample code below, with separate variables that can point to either a 1D array, or a 3D array. I would like to have just one variable in the struct that can point to either a 1D array or a 3D array, where the dimension is set at runtime. I have intermediate knowledge of C, and am a beginner with C++. I'd be willing to accept an answer based on C++ concepts but only if there is no slowdown (or negligible slowdown) compared to using C when iterating over the values. If it's a 3D array, then the for loops that access and change the array's values are the biggest bottleneck in my code. Once the array is set up, I won't need to change the dimension or size of the array.
Is there a way to do this, or should I just settle for always having an extraneous variable in my struct?
#include <iostream>
using namespace std;
typedef struct {
int dim;
int *one_d_arr;
int ***three_d_arr;
} Struct;
int main() {
int count = 0;
int *arr1 = (int*) malloc(2 * sizeof(int));
arr1[0] = 0;
arr1[1] = 1;
int ***arr3 = (int***) malloc(2 * sizeof(int**));
for (int i=0; i<2; i++) {
arr3[i] = (int**) malloc(2 * sizeof(int*));
for (int j=0; j<2; j++) {
arr3[i][j] = (int*) malloc(2 * sizeof(int));
for (int k=0; k<2; k++) {
arr3[i][j][k] = count++;
}
}
}
Struct s;
s.one_d_arr = NULL;
s.three_d_arr = NULL;
cout << "Enter number of dimensions: ";
cin >> s.dim;
if (s.dim==1) {
s.one_d_arr = arr1;
cout << s.one_d_arr[0] << ", " << s.one_d_arr[1] << endl;
}
else if (s.dim==3) {
s.three_d_arr = arr3;
cout << s.three_d_arr[0][0][0] << ", " << s.three_d_arr[0][0][1] << endl;
cout << s.three_d_arr[0][1][0] << ", " << s.three_d_arr[0][1][1] << endl;
cout << s.three_d_arr[1][0][0] << ", " << s.three_d_arr[1][0][1] << endl;
cout << s.three_d_arr[1][1][0] << ", " << s.three_d_arr[1][1][1] << endl;
}
else {
cout << "Must enter 1 or 3" << endl;
}
}
My recommendation is to use two different types here, instead of a single struct. Using an abstract base class, you can make both subclasses conform to a single interface, but they would have different underlying behavior. A very basic example:
class ArrayBase {
int dim;
public:
// This function is pure virtual, which means it's impossible to
// instantiate an instance of ArrayBase. Any class that inherits from
// ArrayBase must implement printArray().
virtual void printArray() = 0;
}
class Array1D : public ArrayBase {
int* array;
void printArray() {
// some code to print this one-dimensional array
}
}
class Array3D : public ArrayBase {
int*** array;
void printArray() {
// some code to print this three-dimensional array
}
}
Later, when you need to use the array, you can dynamically allocate the type you need, like this:
ArrayBase* inputArray;
// if the user wants a 1D array
inputArray = new Array1D();
// if the user wants a 3D array
inputArray = new Array3D();
// this will call the appropriate function to print the array
inputArray->printArray();
If you really want to have a single type, using boost::any is one way to condense your two array pointers into one. I would not recommend this approach, but it would work.
One of the juicy things about the C/C++ pointers is the existence of void pointers. A void pointer can point to anything you want, from int to int ***.
So you can simply use the following code:
#define CAST1(arr) ((int *)arr)
#define CAST3(arr) ((int ***)arr)
#define CAST(arr,i) CAST##i(arr)
typedef struct {
int dim;
void *arr;
} Struct;
int main()
{
Struct s;
cin >> s.dim;
int count = 0;
if (s.dim == 1){
s.arr = malloc(2 * sizeof(int));
CAST(s.arr, 1)[0] = 0;
CAST(s.arr, 1)[1] = 1;
}
else if (s.dim == 3){
s.arr = malloc(2 * sizeof(int ***));
for (int i = 0; i < 2; i++){
CAST(s.arr, 3)[i] = (int **) malloc(2 * sizeof(int **));
for (int j = 0; j < 2; j++){
CAST(s.arr, 3)[i][j] = (int *)malloc(2 * sizeof(int *));
for (int k = 0; k < 2; k++){
CAST(s.arr, 3)[i][j][k] = count++;
}
}
}
}
if (s.dim == 1) {
cout << CAST(s.arr, 1)[0] << ", " << CAST(s.arr, 1)[1] << endl;
}
else if (s.dim == 3) {
cout << CAST(s.arr, 3)[0][0][0] << ", " << CAST(s.arr, 3)[0][0][1] << endl;
cout << CAST(s.arr, 3)[0][1][0] << ", " << CAST(s.arr, 3)[0][1][1] << endl;
cout << CAST(s.arr, 3)[1][0][0] << ", " << CAST(s.arr, 3)[1][0][1] << endl;
cout << CAST(s.arr, 3)[1][1][0] << ", " << CAST(s.arr, 3)[1][1][1] << endl;
}
else {
cout << "Must enter 1 or 3" << endl;
}
system("pause");
return 0;
}

Fundamental Data Types Program

I wrote the following code:
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
char c;
int i;
short int j;
long int k;
float f;
double d;
long double e;
cout << "The size of char is: " << sizeof c << endl;
cout << "The size of int is: " << sizeof i << endl;
cout << "The size of short int is: " << sizeof j << endl;
cout << "The size of long int is: " << sizeof k << endl;
cout << "The size of float is: " << sizeof f << endl;
cout << "The size of double is: " << sizeof d << endl;
cout << "The size of long double is: " << sizeof e << endl;
system("pause");
return 0;
}
The purpose of this program is to print out the size of the fundamental data types, which I think I have accomplished. The other purpose of this program is to print the size of the pointer to each of these data types. I'm having a hard time figuring out how to do this. I understand that a pointer is a variable which stores the address of another variable and that pointers involve the deference operator (*). Can anyone please provide a suggestion? I'm not looking for the answer, just a nudge in the right direction.
int *p; // p is a pointer to an int
So sizeof the pointer would be: sizeof p, which you could print as:
cout << "The size of int pointer is: " << sizeof p << endl;
This is what you need to do print other pointers' sizes.
Dereferencing is only done when you want to access what a pointer is pointing to.
E.g.
int i = 5;
int *p = &i;
*p = 6;
*p = *p + 1;
//etc
Here, you just want to get the size of the pointers. So no dereferencing is needed.

Reading pointers twice is giving garbage values

I want to return an array created in a local function through pointers to the main function. My code is below. The array is returned and I am able to access each element by element once only. The next time it is giving garbage values. What is Wrong?
void DoWork(int** ppOut , int& nSize)
{
int m[5];
for(int i = 0 ; i < 5 ; i++)
{
m[i] = i;
}
nSize = 5;
cout << m[0] << endl;
cout << m[1] << endl;
cout << m[2] << endl;
cout << m[3] << endl;
cout << m[4] << endl;
*ppOut = &m[0];
//delete [] m;
}
void main()
{
int nSize = -1;
int i;
int* f = NULL;
DoWork(&f , nSize);
cout << f[3] << endl;
cout << f[0] << endl;
cout << f[2] << endl;
cout << f[3] << endl;
cout << f[4] << endl;
_getch();
}
Output is:-- 0 1 2 3 4 from local function.
But in main 3 and rest are grabage values
The Problem:
The array m is a local array which does not exist beyond the lifetime of the function DoWork(). When you do so what you end up with is Undefined Behavior, which basically means that you can see any observable behavior because the program ceases to be a C++ standard approved program and so it can show(literally) any behavior.
The Solution:
You will need to extend the lifetime of m so that it is still valid even after the function returns. There are number of ways to do this:
Create an array before the function & pass a pointer to it to the function.
Create a static array inside the function.
Use dynamic memory for the array in function (do remember to release it after usage)
Use global array which can be poulapted inside the function.
Each has own pros and cons and its more of horses for courses.
On a side note, void main() is not the standard specified prototype for main() it should return an int:
int main()
The main function in a C++ program should be int main
Returning a pointer to a local variable exhibits undefined behavior.

Memory location for a pointer passed in a function gets deleted [duplicate]

This question already has answers here:
Pointer errors in the method of transmission(c++)
(4 answers)
Closed 8 years ago.
Question: I can't seem to set a pointer to an address that was created inside of a function. It always gets set to Null, how do I fix this?
Problem: I believe the problem is caused by the variable being created inside of another function. What's happening is that after the function executes, the pointer is set to NULL again.
Code:
void listAdd(int *list, int &length) {
int* tempList = new int[ length + 1 ];
for( int i = 0; i < length; i ++ )
{
(tempList)[ i ] = (list)[ i ];
}
cout << " Previous adress: " << hex << list << endl;
if ( list != NULL )
delete[] list;
list = new int[ length + 1 ];
cout << " New address: " << hex << list << endl << dec;
for( int i = 0; i < length; i ++ )
{
(list)[ i ] = (tempList)[ i ];
}
delete[] tempList;
cout << " Enter a number: ";
int stored = 0;
cin >> stored;
(list)[length -1] = stored;
length ++;
cout << " Length: " << length << "\n";
cout << " value at array point 0: " << (list)[length -1];
cout << "\n retry " << (list)[length-1] <<"\n";
cout << "\n \n \n This is pointing to 0x" << hex << list << '\n' << flush;
}
It seems you would like the changes to list to be valid after the function returned: since list is passed by value, the object manipulated inside the function happens to be a copy of the one you passed in. You probably either want to pass the object by reference, i.e.:
void listAdd(int*& list, int &length) {
// ...
}
... or return the result
int* listAdd(int* list, int& length) {
// ...
return list;
}
list = listAdd(list, length);
Well, realistically, you really really want to encapsulate the objects in a class or just use std::vector<int>.

Having trouble using an array that is returned by a function in C++

I have a function that generates values in an array and returns a pointer to that array. Here's the MWE code:
int *f(size_t s)
{
int *ret=new int[s];
for(size_t a=0;a<s;a++)
{
ret[a]=a;
cout << ret[a] << endl;
}
return ret;
}
note that I have a cout line in for for loop to prove to myself that the array is being populated properly.
Now, here's my problem. I can't find the correct method of using the returned array. Here's what I've been doing:
int main (void)
{
int ary_siz = 10;
int ary[ary_siz];
*ary = *f(ary_siz);
cout << ary[0] << endl;
cout << ary[2] << endl;
cout << ary[3] << endl;
}
The first element in ary seems to be right. The others (ary[1],ary[2]...) are not. Can anyone tell me what I'm doing wrong?
int main (void)
{
int ary_siz = 10;
int *ary = f(ary_siz);
cout << ary[0] << endl;
cout << ary[2] << endl;
cout << ary[3] << endl;
delete [] ary;
}
The assignment
*ary = *f(ary_siz);
copies a single element. Use
int main (void)
{
int ary_siz = 10;
int *ary = f(ary_siz);
delete[] ary;
}
fixing the memory leak as well
You allocate an array in the function and you just assign its first element to the first element of your stack-allocated array, instead of just using the returned array.
you should do something like that:
int main (void)
{
int ary_siz = 10;
int *ary;
ary = f(ary_siz);
cout << ary[0] << endl;
cout << ary[2] << endl;
cout << ary[3] << endl;
delete[] ary // don't forget to release the memory
return 0; // You should return something in the main function
}
Moreover, in C++ you should use vectors instead of "bare-metal" arrays whenever possible.
How about this?
int *ary = f(ary_siz);
The you can just use the [] operator as you do in the couts.