Changing the value of a int variable through pointers passed as arguments? - c++

I want to modify values of some variables of a particular class by accessing address of these variables from another different class through a function. So, to access this address I try to pass pointers-to-variables as arguments to a function, where these pointers-to-variables will be set with the address of the variables. To learn how to do it, I'm trying to mimic in a simple program.
Here is my code:
#include <iostream>
using namespace std;
int numberA = 100;
int numberB = 200;
void referenceSetter(int *a, int *b)
{
*a = numberA;
*b = numberB;
}
void numberOutput()
{
cout << "A = " << numberA << endl;
cout << "B = " << numberB << endl;
}
int main() {
int *testA = 0;
int *testB = 0;
referenceSetter(testA, testB);
*testA = 30;
*testB = 40;
numberOutput();
return 0;
}
As you could see I declare numberA and numberB as global variables and set their values. The I try to get the address of these two variables through the function referenceSetter function and then after that I try to modify the values in those variables using the references. Apparently, I'm doing something wrong which leads to to have Unhandled Exception error exactly when I try to modify the values and try to set them as 30 and 40 resepectively.
Alternatively I tried the following approach:
#include <iostream>
using namespace std;
int numberA = 100;
int numberB = 200;
void referenceSetter(int *a, int *b)
{
a = &numberA;
b = &numberB;
}
void numberOutput()
{
cout << "A = " << numberA << endl;
cout << "B = " << numberB << endl;
}
int main() {
int *testA;
int *testB;
referenceSetter(testA, testB);
*testA = 30;
*testB = 40;
numberOutput();
return 0;
}
But this approach throws up the error uninitialized local variables testA and testB. Do I have to initialize pointers too?
Please help me find my mistake. Thanks.

The thing you're not understanding is that pointers are passed by value, just like any other variable. If you want the passed pointer to be changed, you need to pass a pointer to a pointer (or a reference to a pointer, but I'll leave that alone, as explaining references at this point will confuse you further).
Your main() is passing NULL pointers to referenceSetter(). The assignment *a = numberA copies the value of numberA (i.e. 100) into the memory pointed to by a. Since a is a NULL pointer, that has the effect of overwriting memory that doesn't exist as far as your program is concerned. The result of that is undefined behaviour which means - according to the standard - that anything is allowed to happen. With your implementation, that is triggering an unhandled exception, probably because your host operating system is detecting that your program is writing to memory that it is not permitted to write to.
If, after the call of referenceSetter() you want testA and testB to contain the addresses of numberA and numberB respectively, you need to change referenceSetter() to something like;
void referenceSetter(int **a, int **b)
{
*a = &numberA;
*b = &numberB;
}
This allows the values passed to be addresses of pointers. *a then becomes a reference to the pointer passed. &numberA compute the address of numberA, rather than accessing its value 100. Similarly for numberB.
The second change is to change main() so it calls the function correctly;
referenceSetter(&testA, &testB);
which passes the address of testA (and testB) to the function, so those pointers can be changed

You are trying to set the contents of address 0 to be equal to the other numbers, so when you're doing *a = numberA you're assigning a value of numberA to memory address 0.
Not sure, but I think what you're trying to achieve is this:
#include <iostream>
using namespace std;
int numberA = 100;
int numberB = 200;
void referenceSetter(int **a, int **b)
{
*a = &numberA;
*b = &numberB;
}
void numberOutput()
{
cout << "A = " << numberA << endl;
cout << "B = " << numberB << endl;
}
int main() {
int *testA = 0;
int *testB = 0;
referenceSetter(&testA, &testB);
*testA = 30;
*testB = 40;
numberOutput();
return 0;
}
This way, using pointers to pointers as arguments for referenceSetter(), you are actually modifying the address that your passed pointers are pointing to.

You are close, but the key is you need to pass the address of the value you want to set. You declare the values as int in main and pass the address by using the & operator:
int *testA = 0;
int *testB = 0;
referenceSetter(&testA, &testB);
*testA = 30;
*testB = 40;
numberOutput();
If you declare testA and testB as pointers in main and pass the pointer, the function gets a copy of the pointer instead of the address of the value you want to set.

Related

A pointer to const int in c++

In c++ I have the next code
int main() {
int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = &i;
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 12"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
Now the same code with constant integer i
int main() {
const int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = (int*)&i; //here I am usint a type conversion
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 1"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
As you can see, in second case with constant integer, there are two different values for *iPtr and const i, but the pointer *iPtr shows to constant i.
Please tell me what happens in the second case and why?
Your second code has undefined behavior. You can't change const data via a pointer-to-non-const. You are lucky your code didn't simply crash outright when trying to modify a read-only value.
In any case, the result you are seeing is because the compiler knows that i is const and has a value that is known at compile time. So the compiler is able to optimize away i in the cout statement and use 1 directly instead. That is why you see 1 when printing i and see 12 when printing *iPtr.
You are trying to remove the const qualifier of your variable.
In C++, you should use const_cast to do that.
However, const_cast can only be used in some precise circomstances: constness should only be removed from pointers/references to data which have been declared non-const at top level, otherwise the compiler may optimize the variable and modifying it through the pointer/reference would result in undefined behaviour.
For example, this is not legal :
const int i = 1;
const int *iPtr = &i;
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Invalid : i is first declared const !!
But this is totally legal :
void modifyConstIntPtr(const int *iPtr) {
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Valid : i is first declared non-const !!
}
void modifyConstIntRef(const int &iRef) {
int &iSuperRef = const_cast<int&>(iRef);
iSuperRef = 3; // Valid : i is first declared non-const !!
}
int main() {
int i = 1;
modifyConstIntPtr(&i);
std::cout << i << std::endl;
modifyConstIntRef(i);
std::cout << i << std::endl;
}
This aspect of C++ is well detailed here: https://stackoverflow.com/a/357607/3412316)

Through what to call the method, if I already created constructor with initialization of array of structures?

I'm trying to call the method displayChoices, member of the class MachineManager through the object of the class. But I already have a constructor with initializing of the array of structures. How I understood when we create an object of the class compiler implicitly create a default constructor of the class.
Question: How to call method displayChoices?
#include "MachineManager.h"
using namespace std;
int main()
{
MachineManager mjp;
mjp.displayChoices();
return 0;
}
struct BrewInfo {
string* DrinkName;
double* Cost;
int* Number;
};
class MachineManager {
static const int Num_Drinks = 3; /// why it works only with static?!!!
BrewInfo* BrewArr[Num_Drinks];
public:
MachineManager()
{
*BrewArr[0]->Cost = 1.25;
*BrewArr[0]->Number = 20;
*BrewArr[1]->DrinkName = "pepsi";
*BrewArr[1]->Cost = 1.15;
*BrewArr[1]->Number = 17;
*BrewArr[2]->DrinkName = "Aloe";
*BrewArr[2]->Cost = 2.00;
*BrewArr[2]->Number = 15;
};
int displayChoices();
}
int MachineManager::displayChoices() // (which displays a menu of drink names and prices)
{
cout << 1;
int choice;
cout << "|1." << *BrewArr[0]->DrinkName << " |2." << *BrewArr[1]->DrinkName << " |3." << *BrewArr[2]->DrinkName << " |" << endl;
cin >> choice;
if (!choice || choice == 0) {
system("slc");
displayChoices();
}
else
return choice;
}
displayChoices has to print a menu in console.
You have a majo bug in your source code. You do not yet understand, how pointer work.
You are defining an array of pointer with BrewInfo* BrewArr[Num_Drinks];.
But these pointers are not initialized. They point to somewhere. Then you are dereferencing those pointers (pointing to somewhere) and assigning a value to somewhere in the memory.
This is a major bug.
The array dimensions for C-Sytle arrays must be a compile time constant.
You cannot write
int x=3;
unt array[x];
This is C99 code (called VLA, Variable length array), but not C++.
Solution for you problem:
Do never use C-Style arrays, like int array[5]. Use STL container like std::vector instead.
Do not use pointers.
This is your major problem. Define your array with BrewInfo BrewArr[Num_Drinks];. Please remove also the pointer from
struct BrewInfo {
string* DrinkName;
double* Cost;
int* Number;
};

Size of an object without using sizeof in C++

This was an interview question:
Say there is a class having only an int member. You do not know how many bytes the int will occupy. And you cannot view the class implementation (say it's an API). But you can create an object of it. How would you find the size needed for int without using sizeof.
He wouldn't accept using bitset, either.
Can you please suggest the most efficient way to find this out?
The following program demonstrates a valid technique to compute the size of an object.
#include <iostream>
struct Foo
{
int f;
};
int main()
{
// Create an object of the class.
Foo foo;
// Create a pointer to it.
Foo* p1 = &foo;
// Create another pointer, offset by 1 object from p1
// It is legal to compute (p1+1) but it is not legal
// to dereference (p1+1)
Foo* p2 = p1+1;
// Cast both pointers to char*.
char* cp1 = reinterpret_cast<char*>(p1);
char* cp2 = reinterpret_cast<char*>(p2);
// Compute the size of the object.
size_t size = (cp2-cp1);
std::cout << "Size of Foo: " << size << std::endl;
}
Using pointer algebra:
#include <iostream>
class A
{
int a;
};
int main() {
A a1;
A * n1 = &a1;
A * n2 = n1+1;
std::cout << int((char *)n2 - (char *)n1) << std::endl;
return 0;
}
Yet another alternative without using pointers. You can use it if in the next interview they also forbid pointers. Your comment "The interviewer was leading me to think on lines of overflow and underflow" might also be pointing at this method or similar.
#include <iostream>
int main() {
unsigned int x = 0, numOfBits = 0;
for(x--; x; x /= 2) numOfBits++;
std::cout << "number of bits in an int is: " << numOfBits;
return 0;
}
It gets the maximum value of an unsigned int (decrementing zero in unsigned mode) then subsequently divides by 2 until it reaches zero. To get the number of bytes, divide by CHAR_BIT.
Pointer arithmetic can be used without actually creating any objects:
class c {
int member;
};
c *ptr = 0;
++ptr;
int size = reinterpret_cast<int>(ptr);
Alternatively:
int size = reinterpret_cast<int>( static_cast<c*>(0) + 1 );

converting int to pointer

I want to save int value to a pointer variable. But I get an error:
#include <iostream>
using namespace std;
int main()
{
int *NumRecPrinted = NULL;
int no_of_records = 10;
NumRecPrinted = (int*)no_of_records; // <<< Doesn't give value of NumRecPrinted
cout << "NumRecPrinted!" << NumRecPrinted;
return 0;
}
I tried doing this but I get 0 as return:
int main()
{
int demo(int *NumRecPrinted);
int num = 2;
demo(&num);
cout << "NumRecPrinted=" << num; <<<< Prints 0
return 0;
}
int demo (int *NumRecPrinted)
{
int no_of_records = 11;
NumRecPrinted = &no_of_records;
}
NumRecPrinted returns as 0
It's sometimes useful to "encode" a non-pointer value into a pointer, for instance when you need to pass data into a pthreads thread argument (void*).
In C++ you can do this by hackery; C-style casts are an example of this hackery, and in fact your program works as desired:
#include <iostream>
using namespace std;
int main()
{
int *NumRecPrinted = NULL;
int no_of_records = 10;
NumRecPrinted = (int*)no_of_records;
cout << "NumRecPrinted!" << NumRecPrinted; // Output: 0xa (same as 10)
return 0;
}
You just need to realise that 0xa is a hexadecimal representation of the decimal 10.
However, this is a hack; you're not supposed to be able to convert ints to pointers because in general it makes no sense. In fact, even in the pthreads case it's far more logical to pass a pointer to some structure that encapsulates the data you want to pass over.
So, basically... "don't".
You want to be doing this:
NumRecPrinted = &no_of_records;
i.e. you're taking the address of no_of_records and assigning it to NumRecPrinted.
And then to print it:
cout << "NumRecPrinted!" << *NumRecPrinted;
i.e. you're dereferencing NumRecPrinted which will get the int stored at the memory address pointed to by NumRecPrinted.
#include <iostream>
using namespace std;
int main()
{
int *NumRecPrinted = NULL; // assign pointer NumRecPrinted to be valued as NULL
int *NumRecPrinted2 = NULL;
int no_of_records = 10; // initialize the value of the identificator no_of_records
NumRecPrinted = (int*)no_of_records; // sets a pointer to the address no_of_records
NumRecPrinted2 = &no_of_records; // gives a pointer to the value of no_of_records
cout << "NumRecPrinted!" << NumRecPrinted; // address of no_of_records 0000000A
cout << "NumRecPrinted!" << *NumRecPrinted2; // value of no_of_records 10
system("pause"); // ninja
return 0;
}
Here is the corrected version:
#include <iostream>
using namespace std;
int main()
{
int *NumRecPrinted = NULL;
int no_of_records = 10;
NumRecPrinted = &no_of_records; // take the address of no_of_records
cout << "NumRecPrinted!" << *NumRecPrinted; // dereference the pointer
return 0;
}
Note the added ampersand and the asterisk.
(int *)no_of_records gives you a pointer to the address no_of_records. To get a pointer to the value of no_of_records, you need to write &no_of_records.
I really like using union for this sort of stuff:
#include <iostream>
using namespace std;
int main()
{
static_assert(sizeof(int) == sizeof(int*));
union { int i; int* p; } u { 10 };
cout << "NumRecPrinted! " << u.p;
return 0;
}

Stack memory allocation

It is being said that local variable will be allocated and deallocated automatically when function ends in C/C++.
According to my understanding, when having been deallocated, the value held by local variable also be destroyed!!! Please correct me if i'm wrong
Consider following code:
void doSomething(int** num)
{
int a = 10;
*num = &a;
} // end of function and a will be destroyed
void main()
{
int* number;
doSomething(&number);
cout << *number << endl; // print 10 ???
}
Could anybody clarify for me?
You are correct. your cout may or may NOT print 10. It will invoke undefined behavior.
To make a bit more of a note, try running the following code under your compiler with no optimizations enabled.
#include <iostream>
using namespace std;
void doSomething(int** num)
{
int a = 10;
*num = &a;
}
void doSomethingElse() {
int x = 20;
}
int main()
{
int* number;
doSomething(&number);
doSomethingElse();
cout << *number << endl; // This will probably print 20!
}
In this case, the integer a is on the stack. You are returning the address of that variable to the main program. The value at that address location after the call is undefined. It is possible in some situations that it could print 10 if that portion of the stack was not overwritten (but you certainly would not want to rely on it).
The content of the memory isn't actually destroyed.
For this case, num will point to a location which isn't being allocated for any variable, but it will hold it's content, which was set to 10.
The memory being pointed to has been released back to the system. That means that it will hold whatever value it had until the system assigns that block of memory to another variable and it gets overridden with a value.
Local variables are released when they go out of scope. If you are trying to return a value using an out parameter to a function:
void doSomething(int** num)
{
int* a = new int;
*a = 10;
*num = a;
}
int main()
{
int* number = 0;
doSomething(&number);
std::cout << *number << std::endl; // print 10 ???
if (number) delete number;
}
Though, for something this simple, you are better off just doing this:
int doSomething()
{
return 10;
}
int main()
{
std::cout << doSomething() << std::endl;
}