This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 5 years ago.
I'm new to C++ coming from Java so forgive me for being naive, but I'm trying to pass an array out of a function. I know the way to do this is to pass a pointer, like so:
int *foo(){
int arr[3] = {1, 2, 3};
int *arrptr = arr;
return arrptr;
}
And then to access that array:
int main(){
int *arrptr = foo(); //create a pointer to array
//cout all elements
for(int x = 0; x < 3; x++)
cout << arrptr[x];
return 0;
}
And naturally, this works just fine. But for some reason in a different code, this same process only returns the first value of the array and the rest seem to be random.
int main(){
stringstream allstats;
allstats << readFile(); //readFile() simply returns a string read from a file
while(!allstats.eof()){ //check for end of stream
string temp;
getline(allstats, temp); //grab a line from allstats and put it into temp
double *arr = calculateStats(temp); //create pointer to array of stats calculated for temp
// print arr
for(int x = 0; x < 6; x++)
cout << arr[x] << endl;
//****This spits out the correct value for arr[0] but for the rest of the array
//****it is values like 8.58079e-306 which tells me those addresses have been
//****overwritten.
}
return 0;
}
//calculate stats for each player, return as formatted string
double* calculateStats(string player){
//cut for conciseness, just know it works and the proper values are in the following array
//create stat array
double statarr[6] = {(double)BA, (double)OB, (double)H, (double)BB, (double)K, (double)HBP};
//create pointer to stat array
double *ptr;
ptr = statarr;
return ptr;
}
In Java it would be as simple as just returning an array and the job is done. Is this even possible in C++ or is this just beyond my level of understanding and the solution is much more complicated than I thought?
You cannot have pointer references to local arrays in external functions, since once the local function exits it's stack may be reused and the data in the local variables will contain trash.
You can add word static to your local arrays declaration for it's memory to be persistent across other functions (and repeated calls). Although that is not a recommended solution at all here.
Change:
double statarr[6] = {(double)BA, (double)OB, (double)H, (double)BB, (double)K, (double)HBP};
To:
static double statarr[6] = {(double)BA, (double)OB, (double)H, (double)BB, (double)K, (double)HBP};
Although, a better solution would be to not declare the array local to calculateStats
Something like:
//calculate stats for each player, return as formatted string
double* calculateStats(string player, double *outArr){
//cut for conciseness, just know it works and the proper values are in the following array
//create stat array
outArr[0] = (double)BA;
outArr[1] = (double)OB;
outArr[2] = (double)H;
outArr[3] = (double)BB;
outArr[4] = (double)K;
outArr[5] = (double)HBP;
return outArr;
}
Then have:
int main(){
stringstream allstats;
allstats << readFile(); //readFile() simply returns a string read from a file
while(!allstats.eof()){ //check for end of stream
string temp;
getline(allstats, temp); //grab a line from allstats and put it into temp
double arr[6]
calculateStats(temp, arr) //create pointer to array of stats calculated for temp
// print arr
for(int x = 0; x < 6; x++)
cout << arr[x] << endl;
//****This spits out the correct value for arr[0] but for the rest of the array
//****it is values like 8.58079e-306 which tells me those addresses have been
//****overwritten.
}
return 0;
}
Related
I am a getting a segment fault when trying to input data for my array of pointers. Im pretty new to coding so any help would be great. My task was to make an array of pointers then display, swap them around and than sort them
#include <iostream>
using namespace std;
float getValueFromPointer(float* thePointer)
{
return *thePointer;
}
float* getMinValue(float* a, float* b)
{
if (*a < *b)
{
return a;
}
else
{
return b;
}
}
int main()
{
int arraySize;
cout << "Enter the array size: ";
cin >> arraySize;
float** speed = new float*[arraySize]; // dynamically allocated array
for(int i = 0; i < arraySize; i++)
{
cout << "Enter a float value: ";
cin >> *speed[i];
}
// Core Requirement 2
for (int i = 0; i < arraySize; i++)
{
float value = getValueFromPointer(*speed+i);
cout << "The value of the element " << i << " is: ";
cout << value << endl;
}
//float *pointerToMin = getMinValue(&speed[0], &speed[arraySize - 1]);
//cout << *pointerToMin << endl;
delete [] speed;
speed = NULL;
return 0;
}
You’ve only allocated space for the outer array but you need to also allocate space for each of the internal floats.
So before calling this line:
cin >> *speed[i];
You need to first allocate space for it:
speed[i] = new float;
Your problem is that you've allocated an array of float pointers. You need to allocate an array of floats. So currently you have no memory allocated for the actual floats. If you do this, you'll allocate that memory:
float *speed = new float[arraySize];
You don't have any need for a 2D/jagged array that I can see. If you start with the code above, the compiler errors should lead you right in the direction. (Basically you will start removing * from a lot of places in your code.)
EDIT
Based on your requirement that I misunderstood, a possible approach is the following. The other answer (the one that isn't mine) makes sense in broader scenarios than this, but hopefully this is sort of another angle to think about that rather arbitrary problem you're trying to solve:
int main()
{
float *pFloats = new float[10];
float **ppFloats = new float*[10];
//assign float values and pointers to them in same loop
for (int i = 0; i < 10; i++)
{
pFloats[i] = i;
ppFloats[i] = &pFloats[i];
}
//swap two arbitrary pointers
float *pTemp = ppFloats[4];
ppFloats[4] = ppFloats[5];
ppFloats[5] = pTemp;
//print our float array
for (int i = 0; i < 10; i++)
printf("%f\n", pFloats[i]);
//print our float array *through* our pointers
for (int i = 0; i < 10; i++)
printf("%f\n", *ppFloats[i]);
delete[] ppFloats;
delete[] pFloats;
}
Ignore the hard-coded constants, etc...The point here is that I've created a contiguous memory area for the floats, and then created an array of float pointers on top of it. Note that I can sort my pointer array with zero impact on the original array. There are much smarter ways to do this, but...looks like you're learning about raw pointers, so...
Contrast with the other answer which creates jagged memory for the floats (1 at a time, on demand, not necessarily contiguous).
This question already has answers here:
Function does not change passed pointer C++
(4 answers)
Closed 5 years ago.
I am passing a dynamic array to a function with a value that is meant to be added to the array and when I enlarge and reset the array dynamically and iterate over the array I find the last value of the array is a garbage value rather than what is expected. I've looked at a few other posts on SO as well as some documentation and i'm stumped on what i'm doing wrong. I would prefer to use a vector, but my assignment requires a dynamic array unfortunately. Any thoughts? Thanks.
Post above is passing pointers to vectors by reference and has nothing to do with enlarging dynamic arrays
Main
cout << "Please enter the size of the array of integers you would like to create: ";
cin >> size;
cout << "\nPlease enter your integers:\n";
int *integerArray = new int[size];
//store values in array
for (int dynamicArrayDataCounter = 0; dynamicArrayDataCounter < size; dynamicArrayDataCounter++)
cin >> integerArray[dynamicArrayDataCounter];
cout << "\n Please enter the integer you would like to insert into this array: ";
cin >> userInt;
InsertIntegerToSortedList(integerArray, userInt, size);
//Print array for proof
for (int counterPrinter = 0; counterPrinter < size + 1; counterPrinter++)
cout << endl << integerArray[counterPrinter];
//Remove memory and repoint dangling pointer
delete [] integerArray;
integerArray = NULL;
return 0;
}
Function
void InsertIntegerToSortedList(int *integerArray, int userInteger, int size)
{
//Declare new array to add index position for integerArray
int *resizedArray = new int[size + 1];
bool numInserted = false;
for (int counter = 0; counter < size + 1; counter++)
{
if (integerArray[counter] < userInteger)
{
resizedArray[counter] = integerArray[counter];
}
else if ((integerArray[counter] > userInteger && integerArray[counter - 1] < userInteger) || integerArray[counter] == userInteger || (integerArray[counter] <= userInteger && size - counter == 1))
{
resizedArray[counter] = userInteger;
numInserted = true;
}
else if (numInserted)
resizedArray[counter] = integerArray[counter - 1];
}
//Store resizedArray values in integerArray
integerArray = resizedArray;
//Remove dynamic array on heap and repoint dangling pointer
delete[] resizedArray;
resizedArray = NULL;
}
In
void InsertIntegerToSortedList(int *integerArray, int userInteger, int size)
you are passing the pointer integerArray by value, hence at the exit of the function you end up not modifying it. Pass it by reference, like
void InsertIntegerToSortedList(int* & integerArray, int userInteger, int size)
Furthermore, as mentioned in the comments, you're doing it slightly wrong. First, copy the array elements into resizedArray. Next, you need to delete the old array,
delete[] integerArray;
and finally assign to the newly allocate array to integerArray
integerArray = resizedArray;
That's all is needed, now integerArray will point to the memory that was allocated via resizedArray. No need to set resizedArray to NULL, it is just a local variable that will cease to exist at the exit of the function. What you care about is just the address of the memory you allocated, and you already have that stored into integerArray pointer.
I need to implement a function that modifies an array. The new array may be a different size. cout prints 1. I understand what's wrong with this code but I just cannot figure out what the syntax is.
//tried this..
int reduce(int *array[])
{
*array = new int[1];
(*array)[0] = 6;
return 0;
}
//also tried this..
int reduce(int array[])
{
array = new int [1];
array[0] = 6;
return 0;
}
int main()
{
int a[1] = {1};
int *p = a;
reduce(&p);
cout << a[0];
return 0;
}
Don't understand your question correctly, but this is what you may do:
void reduce(int *a, int size)
{
for (int i =0; i < size; ++i) {
*(a+i) = 6; // or whatever value to want to
}
}
Call it this way:
int main(){
int a[5] = {1, 1, 1, 1, 1};
int *p = a;
reduce(p, 5);
for (int i =0; i < 5; ++i) { cout << a[i]<<endl; }
return 0;
}
EDIT
What you are trying to do can be vaguely done this way:
int * reduce (int **b, int size) {
*b = new int[size];
for (int i =0; i < size; ++i) {
*(*b + i) = 6;
}
return *b;
}
int main(){
int a[5] = {1, 1, 1, 1, 1};
int *p = a;
p = reduce(&p, 5);
cout << p[0];
cout << p[1];
cout << p[2];
cout << p[3];
cout << p[4];
delete [] p;
return 0;
}
But it still wont change where a is pointing to.
What you are trying to do is not possible with statically defined arrays.
When you use an array like
int a[1] = {1};
you cannot change the size of the array at run time, you cannot make it point to dynamically allocated memory. You may only access and modify the elements the array. That's it.
The function reduce changes where p points to but it does not change the elements of a.
If you want to modify the contents of a, you can simply use a as an argument, and set the values.
MODIFIED:
You want to modify array a, try this :
int reduce(int **array)
{
*array = new int[1];
(*array)[0] = 6;
return 0;
}
int main()
{
int *a = new int[1];
reduce(&a);
cout << a[0];
return 0;
}
First of all, the formal parameter int* array[] actually is the same as int** array (you can think of it as a two-dimensional array). This is probably not what you want.
The answer of #everettjf will only work if you do not change the size of the array. A possible solution (that completely replaces the array) would be
#include <iostream>
void print_array(int[],int);
int* reduce(int array[]) {
// get rid of the old array
delete[] array;
// create a new one
array = new int[7]{8,4,6,19,3,56,23};
// need to return the new address, so that
// the main function is informed on the new
// address
return array;
}
int main() {
// initialize array
int *a = new int[1]{4};
print_array(a,1);
// "change" array by completely replacing it
a=reduce(a);
print_array(a,7);
return 0;
}
// simply prints out the array; no error checking!
void print_array(int array[], int length) {
std::cout << "[";
for (int i = 0; i < length ; ++i) {
std::cout << array[i] << " ";
}
std::cout << "]" << std::endl;
}
In the reduce function, the initial array is completely deleted. Afterwards, you can create a new one (I chose to just use 7 random numbers). It is important to return that pointer back to the caller (the main method). Otherwise the a pointer in the main method would point to invalid
If you are not forced (by some kind of excercise, for example) to use arrays, you should look into http://en.cppreference.com/w/cpp/container/vector
The premise of your question is invalid. It is not possible to resize an array of automatic storage duration (aka a in main()) after its definition by ANY means in standard C++.
Dynamic memory allocations in either of your reduce() functions will not cause a in main() to be resized.
reduce(&p) will calls the first version of reduce() , which will then change p (so it points at the dynamically allocated memory) but not affect a.
If main() calls reduce(a) or reduce(p) (the two are equivalent, given the initialisation int *p = a) will change neither a nor p, but instead cause a memory leak.
The underlying problem, I suspect, is that you believe - incorrectly - that pointers and arrays are the same thing. They are actually different things, but can be used in the same way in various contexts. And your code is one of the contexts in which they cannot be used interchangeably.
If you want a resizeable array, use a static container (like std::vector<int>) and - if you want a function to resize it, pass it by reference. It manages its own memory dynamically, so is able to dynamically resize itself.
This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 7 years ago.
I have the following code.
int *x = somefuction();//return array of two elements
string s;
cout << x[0] << " and " << x[1];
This code prints unexpected values. But if I comment out "string s;" row it works fine. What is the reason?
Some function is:
int* getRowCol(int l){
int min = floor(sqrt(l));
int max = ceil(sqrt(l));
int area = 100000;
int result[2];
for (int col = min; col <= max; col += 1){
for (int row = min; row <= col; row += 1){
if (col*row < area && row*col>=l){
area = row*col;
result[0] = row;
result[1] = col;
}
}
}
return result;
}
You are returning a pointer to some value that exists on the stack in someFunction(). I.e. a local variable. These don't live past the end of the function call.
int* someFunction()
{
int someInts[2] = {10, 20}; // only exists inside someFunction
return someInts;
}
Perhaps you should use a std::vector, which will take care of allocating memory in a way that is safe to use like this.
It is Undefined Behaviour to dereference this returned pointer in any way. Your code could do absolutely anything.
Try something like this instead:
std::vector<int> someFunction()
{
std::vector<int> someInts {10, 20};
someInts.push_back(30);
return someInts;
}
I have a 3x3 array that I'm trying to create a pointer to and I keep getting this array, what gives?
How do I have to define the pointer? I've tried every combination of [] and *.
Is it possible to do this?
int tempSec[3][3];
int* pTemp = tempSec;
You can do int *pTemp = &tempSec[0][0];
If you want to treat a 3x3 array as an int*, you should probably declare it as an int[9], and use tempSec[3*x+y] instead of tempSec[x][y].
Alternatively, perhaps what you wanted was int (*pTemp)[3] = tempSec? That would then be a pointer to the first element of tempSec, that first element itself being an array.
You can in fact take a pointer to a 2D array:
int (*pTemp)[3][3] = &tempSex;
You'd then use it like this:
(*pTemp)[1][2] = 12;
That's almost certainly not what you want, but in your comment you did ask for it...
Its easyier to use a typedef
typedef int ThreeArray[3];
typedef int ThreeByThree[3][3];
int main(int argc, char* argv[])
{
int data[3][3];
ThreeArray* dPoint = data;
dPoint[0][2] = 5;
dPoint[2][1] = 6;
// Doing it without the typedef makes the syntax very hard to read.
//
int(*xxPointer)[3] = data;
xxPointer[0][1] = 7;
// Building a pointer to a three by Three array directly.
//
ThreeByThree* p1 = &data;
(*p1)[1][2] = 10;
// Building a pointer to a three by Three array directly (without typedef)
//
int(*p2)[3][3] = &data;
(*p2)[1][2] = 11;
// Building a reference to a 3 by 3 array.
//
ThreeByThree& ref1 = data;
ref1[0][0] = 8;
// Building a reference to a 3 by 3 array (Without the typedef)
//
int(&ref2)[3][3] = data;
ref2[1][1] = 9;
return 0;
}
Oh. That's easy!
int aai[3][3];
int* pi = reinterpret_cast<int*>(aai);
You can actually use this awesome technique to cast it into other wonderful types. For example:
int aai[3][3];
int (__stdcall *pfi_lds)(long, double, char*) = reinterpret_cast<int (__stdcall *)(long, double, char*)>(aai);
Isn't that just swell? The question is whether it's meaningful.
You're asking how to lie to your compiler. So the first thing to know is: Why do you want to lie?
int a[20][30];
int* b=&a[0][0];
As Steve pointed out, the proper form is int *pTemp = &tempSec[0][0];. int** pTemp2 = tempSec; does not work. The error given is:
cannot convert 'int (*)[3]' to 'int**' in initialization
It's not stored as an array of pointers to arrays. It's stored as one big vector, and the compiler hides the [a][b] = [a*rowLength+b] from you.
#include <iostream>
using namespace std;
int main()
{
// Allocate on stack and initialize.
int tempSec[3][3];
int n = 0;
for(int x = 0; x < 3; ++x)
for(int y = 0; y < 3; ++y)
tempSec[x][y] = n++;
// Print some addresses.
cout << "Array base: " << size_t(tempSec) << endl;
for(int x = 0; x < 3; ++x)
cout << "Row " << x << " base: " << size_t(tempSec[x]) << endl;
// Print contents.
cout << "As a 1-D vector:" << endl;
int *pTemp = &tempSec[0][0];
for(int k = 0; k < 9; ++k)
cout << "pTemp[" << k << "] = " << pTemp[k] << endl;
return 0;
}
Output:
Array base: 140734799802384
Row 0 base: 140734799802384
Row 1 base: 140734799802396
Row 2 base: 140734799802408
As a 1-D vector:
pTemp[0] = 0
pTemp[1] = 1
pTemp[2] = 2
pTemp[3] = 3
pTemp[4] = 4
pTemp[5] = 5
pTemp[6] = 6
pTemp[7] = 7
pTemp[8] = 8
Note that the Row 0 address is the same as the full array address, and consecutive rows are offset by sizeof(int) * 3 = 12.
Another way to go about doing this, is to first create an array of pointers:
int* pa[3] = { temp[0], temp[1], temp[2] };
Then create a pointer pointer to point to that:
int** pp = pa;
You can then use normal array syntax on that pointer pointer to get the element you're looking for:
int x = pp[1][0]; // gets the first element of the second array
Also, if the only reason you're trying to convert it to a pointer is so you can pass it to a function, you can do this:
void f(int v[3][3]);
As long as the size of the arrays are fixed, you can pass a two-dimensional array to a function like this. It's much more specific than passing a pointer.
Original post follows - please disregard, it is misinformed. Leaving it for posterity's sake ;)
However, here is a link I found regarding memory allocation of 2-dimensional arrays in c++. Perhaps it may be of more value.
Not sure it's what you want, and it's been a while since I've written c++, but the reason your cast fails is because you are going from an array of arrays to a pointer of ints. If, on the other hand, you tried from array to array to a pointer of pointers, it would likely work
int tempSec[3][3];
int** pTemp = tempSec;
remember, your array of arrays is really a contiguous block of memory holding pointers to other contiguous blocks of memory - which is why casting an array of arrays to an array of ints will get you an array of what looks like garbage [that garbage is really memory addresses!].
Again, depends on what you want. If you want it in pointer format, pointer of pointers is the way to go. If you want all 9 elements as one contiguous array, you will have to perform a linearization of your double array.
Let's ask cdecl.org to translate your declaration for us:
int tempSec[3][3]
returns
declare tempSec as array 3 of array 3 of int
Ok, so how do we create a pointer to that? Let's ask cdecl again:
declare pTemp as pointer to array 3 of array 3 of int
returns
int (*pTemp)[3][3]
Since we already have the array 3 of array 3 of int, we can just do:
int (*pTemp)[3][3] = &tempSec;
int tempSec[3][3];
int* pTemp = tempSec[0];