converting int to pointer - c++

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;
}

Related

How can I print the variable that a void pointer points to

I would like the function to return different types depending on different parameter values, but how can I print the variable the void pointer points to
in main()?
#include <iostream>
#include <string>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int param = 5;
return &param;
}
else if (a == 2)
{
double param = 5.5;
return &param;
}
else if (a == 3)
{
string param = "hello";
return &param;
}
else
{
return nullptr;
}
}
int main()
{
void *ptr = func(3);//
cout << ptr;// print the address not the value
getchar();
return 0;
}
param is an automatic variable. You cannot return it and use it outside its scope.
param exists only within func, if you return it, the result is Undefined Behaviour.
To fix it you can either:
allocate param on the heap dynamically. After you do that, you can safely return param address but you have to remember to free it when you don't need it.
Here is correction of your code
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
void * func(int a)
{
if (a == 1)
{
int *param = new int(5);
return param;
}
else if (a == 2)
{
double *param = new double(5.5);
return param;
}
else if (a == 3)
{
char *param = new char[50];
strcpy(param, "test");
return param;
}
return nullptr;
}
int main()
{
int *ptr = (int*)func(1);
cout << *ptr << std::endl; // print the int value
delete ptr;
double *ptr2 = (double*)func(2);
cout << *ptr2 << std::endl; // print the double value
delete ptr2;
char *ptr3 = (char*)func(3);
cout << ptr3 << std::endl; // print the string
delete[] ptr3;
getchar();
return 0;
}
If you can use C++17, you can easily solve it by using a std::variant instead of a void *:
#include<iostream>
#include<string>
#include<variant>
std::variant<int, double, std::string, void *> func(int a) {
if (a == 1) {
int param = 5;
return param;
} else if (a == 2) {
double param = 5.5;
return param;
} else if (a == 3) {
std::string param = "hello";
return param;
} else {
return nullptr;
}
}
int main() {
std::visit([](auto v) {
std::cout << v << std::endl;
}, func(3));
}
See it up and running on wandbox.
In C++11/14 you can do the same with a tagged union. The basic idea is that what you return contains enough information so that the caller can get out of it the original type.
Alternatives exist.
As an example, you could erase the type and return a pair that contains both the original (erased) variable and a pointer to function filled with an instantiation of a function template. The latter will be able to reconstruct the original variable from a void * for it knows its type.
Well, pretty much a great machinery you can avoid to use with a tagged union or a std::variant (more or less a type-safe version of a tagged union at the end of the day).
What you're returning is the address of a local variable. That variable goes out of scope when the function returns, meaning that the memory it was using could be reused. Attempting to dereference that pointer (i.e. access the memory it points to) invokes undefined behavior.
Even if you were returning a valid pointer, the fact that your function returns a void * means that any type information regarding what that pointer was pointing to is lost. You could print one or more bytes starting at that address, but it won't tell you what the original type was.
Even if that pointer were valid, you simply can't have enough information to force safely a cast to something and then print it.
No information of its size, no information of its internal layout. So,you simply can not print what's pointed by a void*, unless you have some information prepared by hand somewhere, and force a static_cast to the known type.
For example:
double x = 1.2;
int y = 5;
int f(void** output) {
static int x;
if ( x++ ) {
*output = &x;
return 1;
}
*output = &y;
return 2;
}
...
void* out;
int r = f(&out);
if ( r == 1 ) cout << *(static_cast<double*>(out));
else if ( r == 2 ) cout << *(static_cast<int*>(out));

Assigning a struct pointer value from struct vector

#include <iostream>
#include <vector>
using namespace std;
struct Sn {
int SnId;
double spentEnergy;
};
class Node {
//other stuff
private:
vector<Sn> SnRecord;
public:
int getBestSn(Sn* bestSn);
void someFunction();
};
int main()
{
Node nd;
nd.someFunction();
return 0;
}
void Node::someFunction() {
//adding some records in vector just for testing purpose
Sn temp;
temp.SnId = 1; temp.spentEnergy = 5;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
temp.SnId = 2; temp.spentEnergy = 10;
SnRecord.push_back(temp);
cout << "Size of SnReocord is " << SnRecord.size() << endl;
//choosing best sn
Sn *bestSn;
int returnCode = -1;
returnCode = getBestSn(bestSn);
if (returnCode == 0){ //means there is a best SN
cout<< "Found best SN with id = "<< bestSn->SnId << endl;
}
else {
cout <<"NO SN "<< endl;
}
}
int Node::getBestSn(Sn* bestSn) {
int tblSize = (int)SnRecord.size();
if (tblSize == 0)
return -1;
//here i have to assign *bestSn a selected value from vector
//suppose SnRecord[2] is best Sn
cout << "Best sn id is " << SnRecord[2].SnId<< endl; //works OK,
bestSn = &SnRecord[2]; ///// giving me core dump ERROR in my own program but in this simplified version it only gives wrong value
return 0;
}
The output now is:
Size of SnReocord is 3
Best sn id is 2
Found best SN with id = 520004336
In my own program it gives me Core dump error, if I comment this line (and make proper other comments according to function call), the error is gone and simulation executes normally.
I saw examples with arrays, the work if a pointer is assigned a value in this way:
int numbers[5];
int * p;
p = &numbers[2]; //works OK.
but for vectors its not working. Or may be its problem of vector of structures, I'm unable to figure out. Any suggestions?
Ok actually the problem is solved by using suggestion of Sn* & bestSn. But I don't understand this solution. Why can't I pass a pointer variable and it saves a pointer value in it which latter could be accessed?

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

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.

Cannot access objects created in array of pointers

I am having trouble accessing objects that I have created in an array of pointers. I have some test code that shows the objects are being created but in my ShowCluster() function it hangs on the first iteration through the second level loop.
The way I believe I have it coded is that I have a Node** object that in essence becomes a 2d array. Since I am using the new operator I don't have to worry about the scope inside the function.
Any ideas on why I cannot display the contents of these objects that I have created. This is just toy code that I want to use to help my understanding of pointers.
Main.cpp
#include <iostream>
#include "Node.h"
void Test(std::string message){
static int testNumber = 0;
std::cout << "[+] Test: " << testNumber << " : " << message << std::endl;
testNumber++;
}
void Default2dNodeArray(Node** myCluster, int height, int width, int vecLength){
Test("Start of array creation.");
myCluster = new Node*[height];
for(int i=0; i<height; i++){
myCluster[i] = new Node[width];
}
Test("End of array creation.");
}
void ShowCluster(Node **myCluster, int height, int width){
Test("Start of Display array.");
for(int i=0; i<height; i++){
Test("Outer for loop");
for(int j=0; j<width; j++){
Test("Inner for loop");
std::cout << myCluster[i][j].myNodeString << " : " << myCluster[i][j].myNodeInt << std::endl;
}
}
Test("End of Display array.");
}
int main(){
int myHeight = 5;
int myWidth =8;
int myVecLength = 4;
Node** myNodeArray;
std::cout << "Starting pointer test" << std::endl;
Test("In main.");
Default2dNodeArray(myNodeArray, myHeight, myWidth, myVecLength);
Test("In main.");
ShowCluster(myNodeArray, myHeight, myWidth);
Test("In main.");
std::cout << "Ending pointer test" << std::endl;
return 1;
}
Node.cpp
#include "Node.h"
#include <stdlib.h>
#include <stdio.h>
#include <sstream>
#include <iostream>
int Node::globalCounter = 0;
Node::Node(){
std::cout << "Node created." << std::endl;
std::stringstream ss;
ss << "Default: " << globalCounter;
myNodeString = ss.str();;
myNodeInt = globalCounter;
myVecLength = new int[3];
globalCounter++;
}
Node::Node(std::string myString, int myInt, int vecLength){
myNodeString = "Non-Default:" + myString;
myNodeInt = globalCounter;
myVecLength = new int[vecLength];
globalCounter++;
}
Node.h
#ifndef NODE_H_
#define NODE_H_
#include <string>
class Node {
public:
static int globalCounter;
std::string myNodeString;
int myNodeInt;
int* myVecLength;
Node();
Node(std::string, int, int);
};
#endif /* NODE_H_ */
Whatever you do to your Node** myCluster variable in the Default2dNodeArray function, it will not be visible within your main function because you pass in myCluster by value. So myNodeArray in main will not be modified. If you want to modify it, either return the new variable from the function, or change the function signature to
void Default2dNodeArray(Node**& myCluster, int height, int width, int vecLength)
(note the reference in the first argument). Using a triple pointer would also be possible, but I think the intention of modifying the passed variable is much better expressed through a reference, especially since you are already dealing with a double pointer here. Also, it leaves the rest of the code untouched.
You're trying to create an array of pointers to Node objects and initialize each one of those pointers to a Node object allocated on the heap, and pass that around as a parameter.
Passing a pointer to a function can be done by value (i.e. the pointer gets copied, you're able to access the memory pointed by dereferencing it but you can't change the original pointer pointed value), by taking its address and passing it to the function, e.g.
Node *ptr = 0x10;
function(&ptr);
void function(Node** ptr_to_ptr) {
(*ptr_to_ptr) = 0x20; // This will modify ptr
}
or by reference (that will also modify the original pointer value)
Node *ptr = 0x10;
function(ptr);
void function(Node*& ref_to_ptr) {
ref_to_ptr = 0x20; // This will modify ptr
}
in your case, since a double pointer is necessary to hold an array of pointers to Node objects and you're trying to pass it around by taking its address, you're going to end up using a triple pointer:
void Default2dNodeArray(Node*** myCluster, int height, int width, int vecLength) {
Test("Start of array creation.");
// Dereference to access the original double pointer value
*myCluster = new Node*[height];
for (int i = 0; i<height; i++){
(*myCluster)[i] = new Node[width];
}
Test("End of array creation.");
}
void ShowCluster(Node*** myCluster, int height, int width) {
Test("Start of Display array.");
for (int i = 0; i<height; i++){
Test("Outer for loop");
for (int j = 0; j<width; j++){
Test("Inner for loop");
std::cout << (*myCluster)[i][j].myNodeString << std::endl;
}
}
Test("End of Display array.");
}
int main(){
int myHeight = 5;
int myWidth = 8;
int myVecLength = 4;
Node** myNodeArray; // Double pointer
std::cout << "Starting pointer test" << std::endl;
Test("In main.");
Default2dNodeArray(&myNodeArray, myHeight, myWidth, myVecLength);
Test("In main.");
ShowCluster(&myNodeArray, myHeight, myWidth);
Test("In main.");
std::cout << "Ending pointer test" << std::endl;
return 1;
}
The above signatures look much scarier than they actually are. Try to figure out the small snippets I posted at the beginning and then move forward to this code.
If you understood the above example, it will be much easier to get that you could also have done it with a reference to a double pointer:
void Default2dNodeArray(Node**& myCluster, int height, int width, int vecLength)
// etc..
One last piece of advice: although this is just a test, remember to free all the allocated memory or you'll end up leaking it!

Pointers and structures

I'm trying to wrap my head around pointers, references and addresses but every time I think I got it something unexpected pops up.
Why don't we need to dereference the structure to set a value in this example?
// pointer_tet.cpp
#include <iostream>
struct example
{
char name[20];
int number;
};
int main()
{
using namespace std;
example anExample = {"Test", 5};
example * pt = &anExample;
pt->number = 6;
cout << pt->number << endl;
int anotherExample = 5;
int * pd = &anotherExample;
*pd = 6;
cout << *pd << endl;
return 0;
}
Thanks!
Edit: Thank you for your answers! What confused me was not being able to set *pt.number = 6.
You are dereferencing pt. You are doing:
pt->number = 6;
This is equivalent to:
(*pt).number = 6;
The -> operator provides a convenient way to access members through a pointer.
You can do
anExample.number = 6;
OR
(*pt).number = 6;
Read cplusplus.com pointer tutorial might help.