Doubly link list - c++

I am trying to make a memory efficient doubly linked list. The list stores the XOR of the next and the previous addresses, but I am facing an error in the function XOR. The error is:
[Error] cast from 'node*' to 'unsigned int' loses precision [-fpermissive]
My code is:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int data;
node *next;
}*start,*temp;
node* XOR(node *a,node *b)
{
return (node *)((unsigned int)(a)^(unsigned int)(b));
}
void push(int data)
{
node *a=new node;
a->data=data;
a->next=XOR(start,NULL);
if(start!=NULL)
start->next=XOR(start->next,a);
start=a;
}
void disp()
{
temp=start;
node *prev,*cur;
while(temp)
{
cout<<temp->data<<" ";
if(temp==start)
{
prev=temp;
temp=temp->next;
}
else
{
cur=temp;
temp=XOR(temp->next,prev);
prev=cur;
}
}
}
main()
{
start=NULL;
push(1);
push(2);
push(3);
push(4);
push(5);
push(6);
push(7);
push(8);
}

An unsigned int is not guaranteed to be as large as a a pointer, in many cases a pointer is 64 bits and an unsigned int 32 bits. Therefore in this case the upper 32 bits are discarded, invalidating the pointer. You need a uintptr_t instead of an unsigned int.
The corrected code must first:
#include <cstdint>
Somewhere at the top in order to add a declaration for uintptr_t as well as a variety of other useful types and second change the line:
return (node *)((unsigned int)(a)^(unsigned int)(b));
To:
return (node *)((uintptr_t)(a)^(uintptr_t)(b));
Please take a look here for a much better explanation of how uintptr_t and other similar types work http://www.cplusplus.com/reference/cstdint/
Finally I shall mention that in most modern machines a xored linked list will actually be slower, not faster than a normal doubly linked list as the technique makes it much harder for the CPU and compiler to predict what you are doing and optimise well and this effect is greater than the speed boost from small space saving.

You should use uintptr_t defined in #include <cstdint>.
The very purpose of uintptr_t is to be capable of holding a void* pointer and being converted back without loss of precision.
Use
uintptr_t XOR(node *a,node *b)
{
return reinterpret_cast<uintptr_t>(a)^reinterpret_cast<uintptr_t>(b);
}
I wouldn't then cast that back to node* until you eventually return to a uintptr_t that is the valid pointer.
I don't believe it's well defined what happens when you cast a uintptr_t that wasn't directly cast from a pointer to a pointer.

Related

Unsigned long back into pointer to a class

Now, I am doing a exercise in introduction to algorithms by using C++.
The question is :
Explain how to implement doubly linked lists using only one pointer
value x.np per item instead of the usual two (next and prev). Assume
that all pointer values can be interpreted as k-bit integers, and
define x.np = x.next XOR x.prev, the k-bit "exclusive-or" of x.next
and x.prev. (The value NIL is represented by 0). Be sure to describe
what information you need to access the head of the list. Show how to
implement the SEARCH, INSERT and DELETE operations on such a list.
Also show how to reverse such a list in O(1) time.
In the XOR function, I first convert pointer to class into unsigned long and Xor these two value. And then convert the result back to a pointer to class. I don't know why it doesn't work. Here is my code:
struct node
{
int key;
node *np;
} ;
struct list_n
{
node *head;
node *tail;
};
The above are two structs and below is insertion
void insert_element(list_n *_list, int _key)
{
node *present_node= new node;
present_node->key=_key;
present_node->np=xor_gate(nullptr,_list->tail);
if(_list->tail) _list-> tail->np=xor_gate(present_node,xor_gate(nullptr,_list->tail->np ));
if(!_list->head) _list->head=present_node;
_list->tail=present_node;
}
Below is the Xor gate :
node *xor_gate(node *left,node *right)
{
unsigned long result;
result = ( reinterpret_cast<unsigned long>(left) ) ^ ( reinterpret_cast<unsigned long>(right) );
node *output =new node;
output = reinterpret_cast<node*> (result); // yes or no
return output ;
}
void list_n_inti(list_n *a )
{
a->head =nullptr;
a->tail =nullptr;
}
I have review the code several times. I think the problem is caused by XOR gate.
If you have found the bug please tell me. And if you have any other ways to answer this question. please tell me.
Thank you
There is a memory leak in xor_gate, but I think the code works if you compile it as 32-bits. If you compile it as 64-bits, then unsigned long cannot contain a pointer generally.
try this:
#include <cstdint> // for uintptr_t
node *xor_gate(node *left,node *right)
{
using std::uintptr_t;
uintptr_t result = ( reinterpret_cast<uintptr_t>(left) ) ^ ( reinterpret_cast<uintptr_t>(right) );
return reinterpret_cast<node*> (result);
}

How to to set/get the low bits of a pointer to a struct? [duplicate]

I am trying to use tagged pointers for handling the lock free operations on a list, in order to block the compare-and-swap (CAS) from going through if some other thread operated on the list during this transaction. My node struct and CAS look like this:
struct node {
unsigned long key;
unsigned long val;
struct node * next;
};
static inline bool CAS(std::atomic<node*> node, struct node* oldNode, struct node* newNode)
{
node.compare_exchange_strong(oldNode, newNode, std::memory_order_seq_cst);
}
I found some methods for setting and checking these pointers but it is unclear to me how they work, these are the methods for setting the mask and verifying it.
__inline struct node* setTagMask(struct node* p, int MASK_BIT)
{
return (struct node*) ((uintptr_t)p | MASK_BIT);
}
__inline bool isMaskFlagSet(struct node* p)
{
return ((uintptr_t)p & MASK_BIT) != 0;
}
So what is unclear to me is for example in the setTagMask, if I use it on my list than it will delete all its references to its value and next element as well.
Can anyone explain to me how can I properly set these bits so the other elements of the list remain the same?
The setTagMask function returns a modified version of the pointer p. If you store this modified pointer in your linked-list, then the list gets broken because the modified pointer does not point to a node anymore.
The pointer is modified as follows. The pointer p is converted to an unsigned integer which is capable to store a pointer: uintptr_t.
Then one or more bits are set according to MASK_BIT. Finally, the result is converted back to a pointer and returned.
The function isMaskFlagSet checks whether the mask bits are still set.
The only use case, I can image is: you have to call isMaskFlagSet every time, before you use the pointer. If the mask bits are set, then it is prohibited to actually use the pointer.

Casting int to void pointer

Good day,
I just started to learn void pointers in c++ and now I'm writing binary tree where value stored in each node is void pointer to a value.
struct TreeNode
{
int count;
void* data;
TreeNode *left;
TreeNode *right;
};
The problem occurred in very first method-add method.
my method now takes int a a parameter and return nothing
At the very beginning i create new node.
To do that I need to cast integer into void.
Program compiles and first element adds to root correctly-however then when i send another number to method it stores in root again.
so if in main i have something like
tree.addToTree(12);
tree.addToTree(13);
than it would store 12 first and than right after else statement(code below)how that root->data i 13.
void Tree::addToTree(int num)
{
if(root==NULL){
root= new TreeNode();
root->data=&num;
//((int *)(root->data)) = num;//i tried to convert to void* in this way but it give me segmentation fault
root->left=NULL;
root->right=NULL;
}
else{
//here root value is already changed
int *intPtr = static_cast<int*>(root->data);
cout << "key2" << *intPtrT << endl;
//TreeNode* current= insert(num,root);
}
}
as i understood thats because i use &num so my parameter always tore in one place and a root is "connected" to &num it change as well.
I tried to find solution but was unsuccessful.
Is there a way to cat int to void pointer?
First of all, there are very very few reasons to store something as a void* instead of using a strongly typed method (e.g. template). Your entire problem goes away fairly quickly when you change your code to
template<typename T>
TreeNode
{
TreeNode<T>* left;
TreeNode<T>* right;
T data;
};
That said, the problem you have is that you are storing the address of a copy that will go away once the function goes out of scope:
if(root==NULL)
{
root= new TreeNode();
root->data=&num; // PROBLEM!!!
root->left=NULL;
root->right=NULL;
}
The problem line should be:
root->data = new int(num);
And you will have to properly delete the memory when you are done with it (e.g. when your tree is being destructed).
Alternatively, if you happen to be on a system where sizeof(void*) == sizeof(int), you can do this
root->data = (void*)num;
Which will simply treat the void* member as an integer. This does not work on systems where int is larger than void*.
First of all you should decide if you want to store data by value or by a pointer to it.
In first case having a pointer is just useless, you could use a template like:
template <typename T>
struct TreeNode
{
T data;
..
}
TreeNode<int> node;
This will work even with pointers (like T *data ... data = new int()).
In case you want to store a pointer to data you can also use a template with a type parameter or use a common ancestor class and then subclass it with the required types, eg:
class TreeData {
}
class TreeDataInt {
int value;
}
struct TreeNode
{
TreeData *data;
..
}
Lastly storying an int inside a void* pointer is something not so encouraged, using void* in C++ to achieve polymorphism is discouraged in general since you have many other tools which are safer and more reliable.
If you really want to store an int inside a void* then you should use the intptr_t type which is an integer that is convertible to a pointer. Eg:
#include <cstdint>
intptr_t value = 50;
node->data = static_cast<void*>(value);
intptr_t value2 = static_cast<intptr_t>(node->data);
This will save the value of the integer directly as an address inside the void*. This means that you can't dereference the pointer itself.
By the way root->data=&num is wrong since you are assigning to data the address of an automatic allocated variable which will become invalid when exiting its scope.
One problem I see is this (not the answer, just a problem)... in the function
void Tree::addToTree(int num)
{
if(root==NULL){
root= new TreeNode();
root->data=&num;
You are assigning the address of an automatic variable to data. The trouble is that as soon as the function exits, this variable will no longer exist (it is said to go out of scope) and so you have what's known as a dangling pointer, i.e., a pointer that points to an area of memory that is no longer used or is no longer used for the original purpose that the pointer expects.
You could fix this in three ways.
If you only want to store ints or any data type whose width is le that sizeof(void *), you could do root->data = (void *)num (note I cast the value of the variable to a void* and not the address of the variable). Or you could, as I see Zac has suggested too,
Create a copy of the variable and store the copies address. root->data = new int(num);. In this case you must make sure to delete the memory when you destroy the tree
Use templates as others have suggested (this is the better way) - I'll leave this point as others have covered it.
The other bit of you question where you have the comment
//((int *)(root->data)) = num;//i tried to convert to void* in this way but it give me segmentation fault
The reason this fails is because root->data at this point is just a pointer... it doesn't point anywhere (meaningful) yet. Thus when you try to dereference it, you are trying to access some memory that does "exist" yet (either pointer is NULL or has an invalid address), and so you seg fault.
When using a pointer in this way you need to create some memory and then make the pointer point to that memory, e.g. root->data = new int;. Once you have done that, you can then assign a value to that location in memory, e.g., *(root->data) = 1234;

Casting Function Pointer to Integer in C++

I have an array of unsigned integers that need to store pointers to data and functions as well as some data. In the device I am working with, the sizeof pointer is the same as sizeof unsigned int. How can I cast pointer to function into unsigned int? I know that this makes the code not portable, but it is micro controller specific. I tried this:
stackPtr[4] = reinterpret_cast<unsigned int>(task_ptr);
but it give me an error "invalid type conversion"
Casting it to void pointer and then to int is messy.
stackPtr[4] = reinterpret_cast<unsigned int>(static_cast<void *> (task_ptr));
Is there a clean way of doing it?
Edit - task_ptr is function pointer void task_ptr(void)
Love Barmar's answer, takes my portability shortcoming away. Also array of void pointer actually makes more sense then Unsigned Ints. Thank you Barmar and isaach1000.
EDIT 2: Got it, my compiler is thinking large memory model so it is using 32 bit pointers not 16 bit that I was expecting (small micros with 17K total memory).
A C-style cast can fit an octogonal peg into a trapezoidal hole, so I would say that given your extremely specific target hardware and requirements, I would use that cast, possibly wrapped into a template for greater clarity.
Alternately, the double cast to void* and then int does have the advantage of making the code stand out like a sore thumb so your future maintainers know something's going on and can pay special attention.
EDIT for comment:
It appears your compiler may have a bug. The following code compiles on g++ 4.5:
#include <iostream>
int f()
{
return 0;
}
int main()
{
int value = (int)&f;
std::cout << value << std::endl;
}
EDIT2:
You may also wish to consider using the intptr_t type instead of int. It's an integral type large enough to hold a pointer.
In C++ a pointer can be converted to a value of an integral type large enough to hold it. The conditionally-supported type std::intptr_t is defined such that you can convert a void* to intptr_t and back to get the original value. If void* has a size equal to or larger than function pointers on your platform then you can do the conversion in the following way.
#include <cstdint>
#include <cassert>
void foo() {}
int main() {
void (*a)() = &foo;
std::intptr_t b = reinterpret_cast<std::intptr_t>(a);
void (*c)() = reinterpret_cast<void(*)()>(b);
assert(a==c);
}
This is ansi compliant:
int MyFunc(void* p)
{
return 1;
}
int main()
{
int arr[2];
int (*foo)(int*);
arr[0] = (int)(MyFunc);
foo = (int (*)(int*))(arr[0]);
arr[1] = (*foo)(NULL);
}

using Pointers to a series of integers in C++

I am trying to make a c++ program with a class which holds integers on the "heap" and has only one method, pop() which returns the first item in the class and removes it. This is my code so far:
#include <iostream>
using namespace std;
class LinkList {
int *values; //pointer to integers stored in linklist
int number; // number of values stored in linklist
public:
LinkList(const int*, int); // Constructor (method declaration)
int pop(); // typically remove item from data structure (method declaration)
};
LinkList::LinkList(const int *v, int n){
number = n;
*values = *v;
int mypointer = 1;
while (mypointer<n) {
*(values+mypointer) = *(v+mypointer);
mypointer++;
}
}
int LinkList::pop() {
if (number>0) {
int returnme = *values; //get the first integer in the linklist
number--;
values++; //move values to next address
return returnme;
}
else {return -1;}
}
int main() {
int test[] = {1,2,3,4,5};
LinkList l1(test,5);
cout << l1.pop() << endl;
LinkList l2(test,5);
cout << l2.pop() << endl;
return 0;
}
The issue is that its failing at the line *values = *v, if i remove the 4th and 5th lines from the main method, I no longer get this issue, so its go to be a memory management thing.
What I want to do is to get values to point to a continuous bit of memory with integers in. I have tried to use arrays for this but keep just getting random memory addresses returned by pop()
Background: normal I programming in java, I've only be using C/C++ for 2 months, I'm using eclipse IDE in ubuntu, I can make very basic use of the debugger but currently I dont have functioning scroll bars in eclipse so I can't do somethings if they dont fit on my screen.
You are dereferencing an uninitialized pointer (values) at the line *values = *v; which is undefined behavior (UB). What this line says is "get the integer that values points to and assign to it the value pointed by v". The problem with this logic is that values doesn't yet point to anything. The result of this UB is the crash that you receive.
There are many other problems with this code, such as passing a const int* to the constructor with the intent of modifying those values. The biggest problem is that this is not an actual linked list.
*values = *v;
You dereference the values pointer in this line before initializing it. This is the source of the later errors, and the non-errors in the first three lines of main are simply due to luck. You have to allocate space via values = new int[n] and deallocate it in the destructor via delete[] values. std::vector does this work in a clean and exception-safe way for you.
Perhaps the problem is that you're incrementing an integer - mypointer, rather than a a pointer. If the integer requires more than one byte of space, then this might lead to errors. Could you try declaring a pointer and incrementing that instead?
The values member variable is a pointer to uninitialized memory. Before you start copying numbers into it you have to point it to valid memory. For example:
LinkList::LinkList(const int *v, int n){
number = n;
values = new int[n]; // allocate memory
int mypointer = 0;
while (mypointer<n) {
*(values+mypointer) = *(v+mypointer);
mypointer++;
}
}
LinkList::~LinkList() {
delete values; // release memory
}
Also, why do you call this a linked list while in fact you are using a memory array to store your numbers?