C++ - what affects the order of call stack? - c++

I'm so confused with the order of pushing and poping elements of a call stack. I created and initialized a static int* ptr in the void first(). NOTE: I know something unexpected may happen. But what confuses me is that what a call stack does to the recently used address(es).
When the program enters the function call first() in the level of second(), the varibale int a is at the address where int x was before. But after adding the line int z = 99; in the function second(), the variable a still stays in the address ptr points to.
Now something weird happens. If I get rid of the line std::cout << " &a = " << &a << std::endl;, *ptr will become 99 which means variable z is sitting at where x was when I debug or run it again .
I think, the ptr will never be put into the call stack cos it's a static variable and it stays in the data segment, which means ptr never affects the call stack. Therefore, the first-initialised variable in the function second() will be always sitting at where the first-initialised variable in the function first() was, no matter what.
I've got lost under this situation.
Without int z = 99:
void first() {
int x = 7;
static int* ptr = &x;
}
void second() {
int a = 5; // &a = (&x before)
int b = 1;
int c = 2;
int d = 3;
int e = 4;
std::cout << " &a = " << &a << std::endl;
first();
}
int main()
{
first();
second();
first();
}
With int z = 99:
void first() {
int x = 7;
static int* ptr = &x;
}
void second() {
int z = 99;
int a = 5; // &a = (&x before)
int b = 1;
int c = 2;
int d = 3;
int e = 4;
std::cout << " &a = " << &a << std::endl;
first();
}
int main()
{
first();
second();
first();
}
Without std::cout statement:
void first() {
int x = 7;
static int* ptr = &x;
}
void second() {
int z = 99; // &z = (&x before)
int a = 5;
int b = 1;
int c = 2;
int d = 3;
int e = 4;
first();
}
int main()
{
first();
second();
first();
}

Related

Passing arrays of pointers in C++

Not sure what I'm doing wrong here. I'm trying to add a new element and up until the function ends it appears to have worked. But once I try to access anything in it after I get a segmentation fault.
This is just sample code I'm using to try and figure out what I'm doing wrong, with console output to help determine current values.
#include <iomanip>
#include <iostream>
using namespace std;
class foo
{
private:
int z;
public:
foo(int);
int getz();
void setz(int);
};
foo::foo(int zz)
{
z = zz;
}
int foo::getz()
{
return z;
}
void foo::setz(int zz)
{
z = zz;
}
void boo(foo** x, unsigned* n)
{
foo** b = new foo*[3];
for (int i=0; i<2; i++)
b[i] = x[i];
b[2] = new foo(5);
cout << x[0]->getz() << x[1]->getz();
delete[]x;
x = b;
cout << x[0]->getz() << ' ' << x[1]->getz() << ' ' << x[2]->getz();
b = nullptr;
(*n)++;
}
int main() {
foo** a = new foo*[2];
unsigned s = 2;
a[0] = new foo(1);
a[1] = new foo(2);
boo(a, &s);
cout << s;
cout << a[0]->getz();
return 0;
}
The problem is, how you pass your array to your function "boo".
As a general notice, please let me recap how we can use in/out parameters for functions. As you may have heard, we can
pass by value. A copy of the parameter will be made and the all assignmnets to such a variable, will not be available after the function returns.
pass by pointer. In the called function the the pointers will be dereferenced. Basically this is also pass by value. But here the address will be passed. And with dereferencing the address, the original value can be modified.
pass by reference (advised method). A reference to the original variable will be passed to the function and evrything can be handled as if interacting directly with the original variable.
You are passing the foo** as value. That is the reason why it will not work. Delete the parameter will work, but the assignment of x to b will not be visible to the outside world. And after the function "boo" returns, a will be deleted.
Let us look at the good all "swap" example.
// Call by value, will not work. "a" will be changed, but it is a copy
void swapv(int a, int b) {
int temp = a;
a = b;
b = tmp;
}
// Call by address(via pointer) will work. Dereferencing is necessary
void swapp(int *a, int *b) {
int temp = *a;
*a = *b;
*b = tmp;
}
// Call by reference. Recommended solution. Will simply work with same variable names
void swapr(int &a, int &b) {
int temp = a;
a = b;
b = tmp;
}
As you can see. The passing by reference approach is most simple.
Again, what you do is passing "foo**" by value. By the way, "n" is passed via pointer. If you use a typedef or usingstatement, it will get very obvious.
Look at the following piece of code using a using-alias statement.
using fooPtrPtr = foo**;
using fooPtr = foo*;
void boo(fooPtrPtr x, unsigned* n)
{
fooPtrPtr b = new fooPtr[3];
for (int i = 0; i < 2; i++)
b[i] = x[i];
b[2] = new foo(5);
cout << x[0]->getz() << x[1]->getz();
delete[]x;
x = b;
cout << x[0]->getz() << ' ' << x[1]->getz() << ' ' << x[2]->getz();
b = nullptr;
(*n)++;
}
int main() {
fooPtrPtr a = new fooPtr[2];
unsigned s = 2;
a[0] = new foo(1);
a[1] = new foo(2);
boo(a, &s);
cout << s;
cout << a[0]->getz();
return 0;
}
Now you can immediately see the problem. You see immediately that "x" is passed by value to "boo".
But this leads then directly to the recommended and easy solution. Pass it by reference. Like the below:
using fooPtrPtr = foo**;
using fooPtr = foo*;
void boo(fooPtrPtr& x, unsigned& n)
{
fooPtrPtr b = new fooPtr[3];
for (int i = 0; i < 2; i++)
b[i] = x[i];
b[2] = new foo(5);
cout << x[0]->getz() << x[1]->getz();
delete[]x;
x = b;
cout << x[0]->getz() << ' ' << x[1]->getz() << ' ' << x[2]->getz();
b = nullptr;
n++;
}
int main() {
fooPtrPtr a = new fooPtr[2];
unsigned s = 2;
a[0] = new foo(1);
a[1] = new foo(2);
boo(a, s);
cout << s;
cout << a[0]->getz();
return 0;
}
With pointers and pointers to pointers, using or typedef will be very helpful.
Very simple. And without using using the code will be not so easy to understand and could look like the below.
One ampersand "&" after foo** solves the whole problem.
void boo(foo**& x, unsigned& n)
{
foo** b = new foo*[3];
for (int i = 0; i < 2; i++)
b[i] = x[i];
b[2] = new foo(5);
cout << x[0]->getz() << x[1]->getz();
delete[]x;
x = b;
cout << x[0]->getz() << ' ' << x[1]->getz() << ' ' << x[2]->getz();
b = nullptr;
n++;
}
int main() {
foo** a = new foo*[2];
unsigned s = 2;
a[0] = new foo(1);
a[1] = new foo(2);
boo(a, s);
cout << s;
cout << a[0]->getz();
return 0;
}
And last but not least also the version with pass by address / via pointer. Then a lot of dereferencing is necessary, which makes code even harder to read:
void boo(foo*** x, unsigned *n)
{
foo** b = new foo*[3];
for (int i = 0; i < 2; i++)
b[i] = (*x)[i];
b[2] = new foo(5);
cout << (*x)[0]->getz() << (*x)[1]->getz();
delete[](*x);
*x = b;
cout << (*x)[0]->getz() << ' ' << (*x)[1]->getz() << ' ' << (*x)[2]->getz();
b = nullptr;
(*n)++;
}
int main() {
foo** a = new foo*[2];
unsigned s = 2;
a[0] = new foo(1);
a[1] = new foo(2);
boo(&a, &s);
cout << s;
cout << a[0]->getz();
return 0;
}
We can also use aliases to make this a little more readable, but still clumsy.
using fooPtrPtr = foo**;
using fooPtr = foo*;
void boo(fooPtrPtr* x, unsigned *n)
{
fooPtrPtr b = new fooPtr [3];
for (int i = 0; i < 2; i++)
b[i] = (*x)[i];
b[2] = new foo(5);
cout << (*x)[0]->getz() << (*x)[1]->getz();
delete[](*x);
*x = b;
cout << (*x)[0]->getz() << ' ' << (*x)[1]->getz() << ' ' << (*x)[2]->getz();
b = nullptr;
(*n)++;
}
int main() {
fooPtrPtr a = new fooPtr[2];
unsigned s = 2;
a[0] = new foo(1);
a[1] = new foo(2);
boo(&a, &s);
cout << s;
cout << a[0]->getz();
return 0;
}

Array not producing correct output

I have a problem with assigning variables to an array from different functions. I have two functions that produce different numbers. I then want to assign those numbers to a private array in the same class. When I do this the array returns large negative numbers.
// Array.h
class Array {
private:
int W = A;
int Q = B;
int sum[2] = {W, Q};
public:
int A;
int B;
int num1();
int num2();
int add();
};
// Array.cpp
#include<iostream>
using namespace std;
#include "Array.h"
int Array::num1()
{
int x = 3;
int y = 4;
A = x + y;
cout << A << endl;
return A;
}
int Array::num2()
{
int x = 2;
int y = 5;
B = x + y;
cout << B << endl;
return B;
}
int Array::add()
{
for(int i = 0; i < 2; i++)
{
cout << sum[i] << endl;
}
return 0;
}
// main.cpp
#include <iostream>
#include "Array.h"
int main() {
Array sumTotal;
sumTotal.num1();
sumTotal.num2();
sumTotal.add();
return 0;
}
Problem is here:
int W = A;
int Q = B;
int sum[2] = { W, Q };
You are just coping value from A and B to W and Q.
And later when you set A and B, those changes are not reflected to W or Q.
Thus leaving W and Q uninitialized.
Note: consider researching more about C++ topic in field of arrays, pointers and references.
This is modified code that works ok:
#include <iostream>
using namespace std;
class Array {
private:
int sum[2];
public:
int num1();
int num2();
int add();
};
int Array::num1()
{
int x = 3;
int y = 4;
sum[0] = x + y;
cout << sum[0] << endl;
return sum[0];
}
int Array::num2()
{
int x = 2;
int y = 5;
sum[1] = x + y;
cout << sum[1] << endl;
return sum[1];
}
int Array::add()
{
for (int i = 0; i < 2; i++)
{
cout << sum[i] << endl;
}
return 0;
}
int main(int argc, char** argv)
{
Array sumTotal;
sumTotal.num1();
sumTotal.num2();
sumTotal.add();
return 0;
}
The reason you are getting garbage values (large negative numbers, in your case) is that you are not initializing A or B to any meaningful values, and then you are not updating sum when you call num1, or num2.
You should initialize A and B to something meaningful in the class, or at least default initialize it.
Then you need to update sum in num1, like this:
int Array::num1()
{
int x = 3;
int y = 4;
A = x + y;
sum[0] = A; // <- add this
cout << A << endl;
return A;
}
and do a similar thing inside num2.
You also have 2 variables W, and Q inside your class which don't seem to serve any purpose. Apart from the issue with initializing them incorrectly with garbage values, you don't even need them; you could just use A, and B instead.

Why is it necessary to define an array as a global variable when returning an array in a function? [duplicate]

This question already has answers here:
How to return an array from a function?
(5 answers)
Closed 2 years ago.
Why is it necessary to define an array as a global variable when returning an array in a function?
int v[10] = { 1,2,3,44,55,66,77,8,9,1 };
auto fun()->int(*)[10]
{
//int v[10] = { 1,2,3,44,55,66,77,8,9,1 };/
return &v;
}
int main()
{
auto t = fun();
for (int i = 0; i <= 10; i++)
cout << (*t)[i] << endl;
}
First, your code is C++ and not C, so I'll respond accordingly.
You can return a C++-style std::array, which is an object rather than a C-style array and thus can be returned by value:
#include <iostream>
#include <array>
int v[10] = { 1,2,3,44,55,66,77,8,9,1 };
auto fun()->std::array<int, 10>
{
std::array<int, 10> v;
v[0] = 5;
v[1] = 32;
//int v[10] = { 1,2,3,44,55,66,77,8,9,1 };/
return v;
}
int main()
{
auto v = fun();
for(size_t i = 0; i < 10; i++) {
std::cout << v[i] << std::endl;
}
}
You could have dynamically allocated the array instead, in which case you return a pointer and the caller is responsible for freeing it:
auto fun2()->int*
{
auto v = new int[10];
v[0] = 1;
// assign other elements
return v;
}
int main()
{
auto t2 = fun2();
for (int i = 0; i < 10; i++)
std::cout << t2[i] << std::endl;
delete[] t2;
}
You're simply not allowed to allocate the array on the stack and then return it, because the lifetime of stack variables is over as soon as your function returns. With that said, this example is valid because the array is allocated in main's stack frame and outlives all of its uses:
void fillIn(int* ar, size_t len) {
for (size_t i = 0; i < len; i++) {
ar[i] = 32; // or whatever logic you want
}
}
int main()
{
int x[10];
fillIn(x, 10);
for (int i = 0; i < 10; i++) {
std::cout << x[i] << std::endl;
}
}

C++ - invalid conversion from 'int' to 'int**'

I have this following code:
#include<iostream>
using namespace std;
void insert(int *a[], const int location, const int numofelements, const int value) {
int n, b[10];
a = *b;
for (int n = numofelements; n > location; n--) {
a[n-1] = a[n];
}
b[location] = value;
*b = a;
}
int main() {
int test[10] = [1,2,3,4,5];
insert(test, 2, 5, 7);
for (int i = 0; i < 6; i++) {
cout << "test[" << i << "] = " << test[i];
}
return 0;
}
And the compiler says:
[Error] invalid conversion from 'int' to 'int**' [-fpermissive]
[Error] invalid conversion from 'int**' to 'int' [-fpermissive]
What does it mean? Thanks
Errors like this mean you are mixing integers and pointers to integers.
There is several cases in your code where that happens.
Lets look at pointers in this example
//defining
int a; //int, a is an integer holding the value
int *b; //*int, a pointer to an integer
int c[10]; //*int, arrays are to pointers to the first element with some different rules
int **d; //**int, this is a pointer to a pointer
int *d[10];//**int, this is a pointer to a an array, and arrays similar to pointers
//using pointers
a = *b; //* before a pointer returns its value
a = b[0]; //resolving the position of an array also returns its value
b = &a; //& before a value returns the address
Lets take a look at your code
#include<iostream>
using namespace std;
void insert(int *a[], const int location, const int numofelements, const int value) {
int n, b[10];
a = *b; //a is **int. *b means the first element so *b is an int.
for (int n = numofelements; n > location; n--) {
a[n-1] = a[n];
}
b[location] = value;
*b = a; //a is **int. *b means the first element so *b is an int.
}
int main() {
int test[10] = [1,2,3,4,5];
insert(test, 2, 5, 7); //test is a *int, the function expects a **int
for (int i = 0; i < 6; i++) {
cout << "test[" << i << "] = " << test[i];
}
return 0;
}
Here is a tutorial on using pointers

What is wrong with derefrencing this pointer?

While debugging i found that my program stops at: "cout << *ptr ; cout << "\n";" what is wrong with this code?
#include<iostream>
using namespace std;
int *ptr = 0;
void myfun(void);
int main()
{
void myfun();
for(int j = 1; j < 3; j++)
{
ptr = ptr-j ;
cout << *ptr ; cout << "\n";
}
return(0);
}
void myfun(void)
{
int x[3] = {11,12,13};
for(int i = 0; i <3; i++)
{
ptr = &x[i];
ptr = ptr+1;
}
}
You initialized your pointer with zero
int *ptr = 0;
which means that it is a null pointer.
Then you are applying pointer arithmetic to a null pointer. The behavior is undefined. The you are dereferencing the nonsensical pointer obtained in that way. The behavior is undefined.
Note that
void myfun();
in main is not a function call, it is a function declaration. A call to myfun (which was apparently your intent) would look as follows
myfun();
Why did you put that void there in your version of the code?
Your variable ptr is a wild pointer.
Although you let the ptr porint to array x, when the myfun() finish and return the memory of x had been destory. So in the main function, ptr become wild pointer and your program will crash.
You should know that the local variable will be destoried when they are not in their scope.
main function doesn't have access to the data, as scope of the array x[3] is myfun(void). After myfun call (it should be myfun(); instead of void myfun();), ptr will be pointing to an unallocated memory location.
To print the data in main function, you can declare the int x[3] as a global variable.
int *ptr = 0;
void myfun(void);
int x[3] = {11,12,13};
int main()
{
int *temp_ptr;
myfun();
temp_ptr = ptr;
for(int j = 1; j <= 3; j++)
{
temp_ptr = ptr-j ;
cout << *temp_ptr ; cout << "\n";
}
return(0);
}
After following the above answers and a little bit of googling I found out the exact solution to my problem: To return variable sized array from a function.
This is the code:
#include<iostream>
using namespace std;
int * myfun(void);
int main()
{
int *ptr;
ptr = myfun();
int len = (sizeof(ptr)/sizeof(*ptr));
for(int j = 0; j <= len; j++)
{
cout << ptr[j];
}
return(0);
}
int * myfun()
{
static int x[3] = {11,12,13};
return x;
}