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;
}
Related
This question already has answers here:
What happens if I increment an array variable?
(5 answers)
Increment operator on pointer of array errors?
(2 answers)
Closed 2 years ago.
I just got into learning pointers in C++ and I have been trying some different instances of using them to get a better understanding to them but there is some I go into that seems a little weird to me.
The code below is for looping through an array and what I assumed after it ran well that arr is just a pointer to the beginning of the array (because I could do ptr = arr;.
int size = 3;
int arr[size] = {50, 30, 20};
int *ptr;
ptr = arr;
for (int i = 0; i < size; i++) {
std::cout << *ptr << std::endl;
ptr++;
}
But When I try looping through the same array but with using arr instead of ptr without assigning it to arr it gave me an error (lvalue required as increment operand) referring arr++.
This is the Code.
int size = 3;
int arr[size] = {50, 30, 20};
for (int i = 0; i < size; i++) {
std::cout << *arr << std::endl;
arr++;
}
I don't understand why the first one work and the second doesn't although they are both pointers(as far as I know).
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;
}
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:
Returning a reference to a local variable in C++
(3 answers)
Closed 7 years ago.
I think I've got my self confused by following codes. Suppose I have two simple functions:
int* makeiniele()
{
int res[55] = { 0 };
return res;
}
and
void printele(int* wxyz)
{
for (int k = 0; k < 55; k++)
{
cout << wxyz[k] << "\n";
}
}
The problem is when I run the following line:
printele(makeiniele());
I get 55 big negative numbers instead of 55 zeros!
Thank you for your time
Two issues:
1) The array is not initialized to contain 55 zeros, but only 1, remaining 54 elements are going to be some older memory content:
int res[55] = { 0 };
you need to use the memset() function in order to do that efficiently:
int res[55];
memset(res, 0, sizeof(res));
2) The array you declare in the makeiniele() function will be deallocated after returning from the function and (since it was living on the stack) its content is going to be overwritten by the call of next function printele(). Therefore, initializing it correctly won't fix your problems.
A solution would be to consider using malloc() to allocate the array instead. Your makeiniele() function should look like this:
int* makeiniele(){
int *res = malloc(sizeof(int)*55));
memset(res, 0, sizeof(int)*55);
return res;
}
And remember to call free() after you have finished with the array in order to avoid memory leaks.
int* makeiniele()
{
int res[55] = { 0 };
return res;
}
The problem here lies with scope - once a function ends, any variables declared within the function are deleted from memory. Once the function makeiniele terminates, the array res is also deleted from memory. The memory that array took up has been replaced with something else - this 'something else' is what's being printed to your screen. You can verify this with the following code:
int * myvar = new int[55]{ 0 };
int* var = myvar;
printele(var);
delete myvar;
printele(var);
The fist 55 numbers will be zeroes (the variable hasn't been deleted yet). Once the variable is manually deleted with delete the address of it is now pointing to unused memory, so it spits out random numbers. To fix this, replace your makeiniele funciton with this:
int* makeiniele()
{
int * myvar = new int[55]{ 0 };
return myvar;
}
And everything should work fine!
EDIT: As Zereges said, you MUST ensure to end your program with
delete myvar;
to prevent a memory leak.
A little modern C++ answer.
Either using clever array (std::vector)
std::vector<int> makeiniele()
{
std::vector<int> res(55, 0);
return std::move(res);
}
void printele(const std::vector<int>& wxyz)
{
for (int k = 0; k < 55; k++)
{
cout << wxyz[k] << "\n";
}
}
Or using clever pointers (std::shared_ptr)
std::shared_ptr<int> makeiniele()
{
std::shared_ptr<int> res(new int[55]);
std::memset(res.get(), 0, 55 * sizeof(int));
return std::move(res);
}
void printele(std::shared_ptr<int> wxyz)
{
for (int k = 0; k < 55; k++)
{
std::cout << wxyz.get()[k] << "\n";
}
}
I was trying create a 2d array of pointers based on other. Here is a base 2d array:
double **a = new double*[3];
a[0] = new double[3]{ 1, 2, 3 };
a[1] = new double[3]{ 4, 5, 6 };
a[2] = new double[3]{ 7, 8, 9 };
And I want create a 2x2 matrix which should look like this:
5,6
8,9
Finally, I was trying resolve the problem as follow:
double **b = &a[1];
b[0] = a[1];
b[1] = a[2];
Unfortunately, this code does not work as I expect. In addition, I would like to get access to data using negative indices eg. b[-1][-1] should return 1 value.
With:
double a0[] = { 1, 2, 3 };
double a1[] = { 4, 5, 6 };
double a2[] = { 7, 8, 9 };
double* b0[3] = {&a0[1], &a1[1], &a2[1]};
double** b = &b0[1];
you can access with negative index and do:
for (int i = -1; i != 2; ++i) {
for (int j = -1; j != 2; ++j) {
std::cout << b[i][j] << std::endl;
}
}
This approach cannot work. One property of this kind of 2d array is that &A[k+1] = &A[k]+1, but that relationship does not hold between your desired B[0] and B[1], because those are actually &A[1][1] and &A[2][1], which could be miles apart.
What your code actually does is:
double **b = &a[1]; // all right, b points to part of a[]
b[0] = a[1]; // this assignment does nothing, they're already equal
b[1] = a[2]; // this assignment does nothing, they're already equal
This might help you out some and get you on the right track.
#include <conio.h>
#include <iostream>
struct Vec3 {
union {
double d3[3];
struct {
double x;
double y;
double z;
};
};
double& operator[]( int idx );
};
double& Vec3::operator[]( int idx ) {
return d3[idx];
}
typedef Vec3 Row;
struct Matrix {
union {
Row r[3];
struct {
Row row1;
Row row2;
Row row3;
};
};
Row& operator[]( int idx );
};
Row& Matrix::operator[]( int idx ) {
return r[idx];
}
int main() {
Matrix m;
m.row1.x = 1;
m.row1.y = 2;
m.row1.z = 3;
m.row2.x = 4;
m.row2.y = 5;
m.row2.z = 6;
m.row3.x = 7;
m.row3.y = 8;
m.row3.z = 9;
for ( int i = 0; i < 3; i++ ) {
for ( int j = 0; j < 3; j++ ) {
m[i][j] += 10;
std::cout << m[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << "Press any key to quit" << std::endl;
_getch();
return 0;
}
I did not add any error checking or bounds checking into the overloaded operator I just allowed the user to pass any value into it. This you would have to design to your specific needs. I'm just demonstrating an easy way to create a 2D Array or a Matrix like object using unions to have quick access to the subscript or bracket operator. I show a sample use of creating a 3x3 matrix with each value ranging from 1-9 then I use a double for loop to add 10 to each value then print out the new value within the array using the double brackets. This is all done on the stack which is better then using pointers and creating new memory for each place. If you need to use the heap then you could just assign this matrix class its own pointer and create it on the heap instead of every individual element. Another thing that can be done with this is if you need to use this for say int, float or some other data type you can easily template this class or structure.
As for indexing by a negative value; I have not heard of anyone doing so. This isn't to say that it can not be done, but from what I recall on how pointers & arrays behave with indexing according to their association with memory addressing they are 0 based index. This usually means that if we have a memory block a pointer to a double type variable, this usually means that each block of memory in most cases is 8 bytes wide. The very first element resides in the very first memory address location that is assigned to this variable for both the stack and the heap. If you try to use negative numbers which involve pointer arithmetic you begin to traverse memory that doesn't belong to this declared variable. To try and pull off what you are suggesting might require more than just basic C/C++ code can do, you might have to dive into asm to get something like this to work, especially if you want to avoid using if statements within the overloaded operators.