Why are same addresses sent into function? [duplicate] - c

This question already has answers here:
Copy one pointer content to another
(4 answers)
Closed 1 year ago.
I'm working on doubly linked list and I came across the problem. I will paste parts of code step by step I try to explain what's happening.
So I have defined datatype:
typedef struct node {
void *data;
struct node *prev, *next;
} NODE;
In this part of add function might be something wrong. I've checked all scenarios but I don't want to paste unnecessary code.
void add(NODE **phead, NODE **ptail, void *data, int (*cmp)(const void*, const void*)){
NODE *p, *q, *new = (NODE*)calloc(1, sizeof(NODE));
new->data = data;
if(*phead == 0)
*phead = *ptail = new;
else if((*cmp)((*phead)->data, data) > 0){
new->next = *phead;
(*phead)->prev = new;
*phead = new;
}
When I was debugging code I saw that when function pointer is called same addresses were sent as arguments.
NODE *search(NODE *head, NODE *tail, const void *data, int (*cmp)(const void*, const void*)){
if(head == 0)
return 0;
while ((*cmp)(head->data, data) < 0 && (*cmp)(tail->data, data) > 0)
{
head = head->next;
tail = tail->prev;
}
if((*cmp)(head->data, data) == 0)
return head;
else if((*cmp)(tail->data, data) == 0)
return tail;
else
return 0;
}
Compare function which is argument of add and search function is:
int cmp_str(const void *a, const void *b){
return strcmp((const char*)a, (const char*)b);
}
Part of main function where both search and add are called:
int main(){
NODE *head = 0, *tail = 0;
char c, *data = (char*)calloc(20, sizeof(char));
do
{
printf("Add [A], delete [D], write [W], search [S], end [0]: ");
scanf("\n%c", &c);
if(c == 'A'){
get_string(&data);
NODE *p = search(head, tail, data, &cmp_str);
if(p){
p->data = data;
printf("Data updated!\n");
}
else{
add(&head, &tail, data, &cmp_str);
printf("Data added.\n");
}
}
So basically the thing that goes wrong is that only one data is saved. Here I work with strings but the parameters and variables of data is void*. So when I input add two nodes only the data of the last typed is saved. Also in main, every time except first p is found by search function even if it doesn't exist. As I told, debugger's saying that cmp_str receives two arguments of same address, which might be hint to find where the error is.

You are setting data pointer as same for each add operation. It seems you allocated once and using same memory for every cycle. If I'm wrong please correct me.
You need to allocate new memory and deep copy data pointer's content into new->data.
void add(NODE **phead, NODE **ptail, void *data, int (*cmp)(const void*, const void*)){
NODE *p, *q, *new = (NODE*)calloc(1, sizeof(NODE));
new->data = data;
...

The answer is very simple. It is quite common misunderstanding when people learn C.
The data pointer points always to the same memory location.
In add functions you simply assign this reference to all nodes. In C = does not copy the memory referenced by the pointers only assigns the reference.
You need to allocate it at every interaction (in main) or copy it in the add function.
void add(NODE **phead, NODE **ptail, void *data, size_t data_size, int (*cmp)(const void*, const void*)){
NODE *p, *q, *new = calloc(1, sizeof(*new));
//check if calloc did not return NULL
new -> data = calloc(1, data_size);
//check if calloc did not return NULL
memcpy(new->data, data, data_size);
// ...
Some additional remarks:
Use objects not types in sizeof.
Do not cast the result of malloc/calloc. If compiler is giving you errors the it is an indication that you compile the C code using C++ compiler which is not a good idea.

Related

referenced values are lost with stack frame collapse

I am currently attempting to load values from an array into a stack data structure that I have implemented with a linked list. In my push() function I create each new node in my linked list through the use of a pointer so that they do not disappear when the push() stack frame collapses and control returns to reverse(). However, even though I am passing information through the use of pointers, the item I am referencing appears not be returning, as I keep getting NULL values in the calling function despite getting valid values in the called function. Why is this information not returning to my calling function?
#include<stdio.h>
#include<stdlib.h>
struct Node
{
char data;
struct Node* next;
};
void push(char x, struct Node* tp)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node*));
temp->data = x;
temp->next = tp;
tp=temp;
printf("\ntp points to %p", tp);
}
void reverse (char c[])
{
struct Node* tp = NULL;
int i = 0, j = 0;
while (c[i] != '\0')
{
push(c[i], tp);
printf("\ntp points to %p", tp);
i++;
}
}
int main(void)
{
char c[] = {"coolio"};
printf("\n%s", c);
reverse(c);
}
The problem is that push cannot change tp that you pass it from reverse, because tp is passed by value. Change the function to return the value to be assigned to tp, like this:
struct Node* push(char x, struct Node* tp) {
... // your code here
return temp;
}
The call should look like this:
while (c[i] != '\0') {
tp = push(c[i], tp);
printf("\ntp points to %p", (void*)tp);
i++;
}
Note that using %p requires a cast to void*.
Demo.

Add values to a tree

I'm trying to add values to a binary search tree so for that I've written two functions one that create a new node and another which insert these values to the tree
So this is the code
typedef struct Node {
void *data;
struct Node *left;
struct Node *right;
} Node;
Node *createNode(void *data,size_t s){
Node *newNode = (Node *)malloc(s * sizeof(Node));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
void addValueBt(Node ** node, void *data, size_t s,int (* compar)(const void *, const void *)){
if (*node == NULL)
*node = createNode(data,s);
else if (compar((*node)->data,data) > 0)
addValueBt(&(*node)->left, data, s, compar);
else
addValueBt(&(*node)->right, data, s, compar);
}
When I call addValueBt in the main with two different ways (but normally seems to be the same thing) I don't get the same result
1st way:
int main(){
Node *root = NULL;
for(int i = 0; i < 10; i++)
addValueBt(&root, &i, 1, myCompar);
printBt(root,print);//print the whole tree
}
The display gives this:
10
10
10
10
10
10
10
10
10
10
2nd way:
int main(){
int a = 8, b = 9, c = 5, d = 1;
addValueBt(&root, &a, 1, myCompar);
addValueBt(&root, &b, 1, myCompar);
addValueBt(&root, &c, 1, myCompar);
addValueBt(&root, &d, 1, myCompar);
printBt(root,print);
}
The display:
1
5
8
9
"myCompar" compares between two integers
My question is: why it doesn't work when we use the function 'addValueBt' in the loop ?
(normally it should give the same result as for the other one )
Primary problem
As user3386109 correctly pointed out in a comment, the primary problem is that you're storing a pointer to the data in your tree, not a copy of the data. All the nodes end up pointing at the same location, so when that location changes, the value pointed at by the tree changes in all nodes at once.
Secondary issues
In a collection of comments (some of them responses to comment questions by Yasmine, the OP), I noted:
This is tangential to your main problem, but the parameter s is initially confusing. It's always 1 because you only allocate one node at a time. If it was larger, you'd waste the extra space that createNode() does allocate but does not initialize. You could stop using s (assume 1) without causing problems in the visible code.
I mean that in Node *createNode(void *data, size_t s) { Node *newNode = (Node *)malloc(s * sizeof(Node));, you allocate an array of Node structures of the size given by s. However, you initialize only the first structure allocated, and you don't record the size of the array anywhere. This doesn't matter because if you track the calls from main() to addValueBt() to createNode(), the value of s is always 1. But because it is always 1, you really have no need to pass it, so you can simplify the calls all the way down the calling chain.
Note that #user3386109: has identified the problem. You store the same pointer in each element of the tree, so when the pointed at value changes, all the elements of the tree change at the same time. And if the pointed at value goes out of scope, you get undefined behaviour. You either need to make a copy of the data in the createNode() function, which means that you need to know how big the data is so that you can allocate new space to store it, or you need to ensure that a different pointer is passed to the code each time, and those pointers remain valid until the tree is freed.
You can see with your working code, you pass a different pointer each time (a pointer to a different variable). When you repeatedly pass a pointer to the same variable, the same address is stored, so the current value stored at that address is used by all the nodes; they all have the same value.
Part of the problem comes from using void *data; instead of a simple int data;. For the immediate purposes, life would be much, much simpler if your data structure used int data;. You'd have:
Node *createNode(int key)
{
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = data; newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
If you store void *, you really need to know how long the data you're storing pointers to is, so that you can make copies, etc. Your comparator can make assumptions about the length (and you'll be OK as long as those assumptions are correct). So, you'd need:
Node *createNode(void *data, size_t len)
{
void *copy = malloc(len);
memmove(copy, data, len);
Node *newNode = (Node *)malloc(s * sizeof(Node));
newNode->data = copy;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Yasmine commented:
I know but I have to do that so that it can be used with other types like float or char.
At that point, I started to produce the code below.
Working code
Here's an offering dealing with the points made in my comments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct Node
{
void *data;
size_t datalen;
struct Node *left;
struct Node *right;
} Node;
static int cmp_dbl(const void *p1, const void *p2);
static int cmp_int(const void *p1, const void *p2);
static void freeBt(Node *node);
static void printBt(Node *node, void (*print)(const void *));
static void print_dbl(const void *p);
static void print_int(const void *p);
extern Node *createNode(void *data, size_t len);
extern void addValueBt(Node **node, void *data, size_t len, int (*compar)(const void *, const void *));
Node *createNode(void *data, size_t len)
{
void *copy = malloc(len);
// Error check allocation!
memmove(copy, data, len);
Node *newNode = (Node *)malloc(sizeof(*newNode));
// Error check allocation!
newNode->data = copy;
newNode->left = NULL;
newNode->right = NULL;
newNode->datalen = len;
return newNode;
}
void addValueBt(Node **node, void *data, size_t len, int (*compar)(const void *, const void *))
{
if (*node == NULL)
*node = createNode(data, len);
else if (compar((*node)->data, data) > 0)
addValueBt(&(*node)->left, data, len, compar);
else
addValueBt(&(*node)->right, data, len, compar);
}
int main(int argc, char **argv)
{
unsigned seed = time(0);
if (argc == 2)
seed = atoi(argv[1]);
srand(seed);
printf("Seed: %u\n", seed);
Node *root = NULL;
for (int i = 0; i < 10; i++)
addValueBt(&root, &i, sizeof(i), cmp_int);
printBt(root, print_int);
freeBt(root);
root = NULL;
for (int i = 0; i < 10; i++)
{
double d = (double)rand() / RAND_MAX * 1000.0 + (double)rand() / RAND_MAX;
addValueBt(&root, &d, sizeof(d), cmp_dbl);
}
printBt(root, print_dbl);
freeBt(root);
return 0;
}
static int cmp_int(const void *p1, const void *p2)
{
int v1 = *(int *)p1;
int v2 = *(int *)p2;
return (v1 > v2) - (v1 < v2);
}
static int cmp_dbl(const void *p1, const void *p2)
{
double v1 = *(double *)p1;
double v2 = *(double *)p2;
return (v1 > v2) - (v1 < v2);
}
static void print_int(const void *p)
{
printf("%d\n", *(int *)p);
}
static void print_dbl(const void *p)
{
printf("%8.3f\n", *(double *)p);
}
static void printBt(Node *node, void (*print)(const void *))
{
if (node != 0)
{
printBt(node->left, print);
print(node->data);
printBt(node->right, print);
}
}
static void freeBt(Node *node)
{
if (node != 0)
{
freeBt(node->left);
freeBt(node->right);
free(node);
}
}
Here's an example run:
Seed: 1511037421
0
1
2
3
4
5
6
7
8
9
87.907
118.694
140.163
170.833
343.940
412.792
422.254
530.731
557.656
936.981
What changed?
I dropped the parameter s to addValueBt() and createNode(), but added a parameter size_t len. That defines the length of the data. The length is stored in size_t datalen in the Node structure.
The code in createNode() makes a copy of the data it is passed and stores that copy in the tree. This ensures that each node is unaffected by changes to the values in the calling code.
What was added?
I added code for the int comparator (you called yours myCompar(); I called mine cmp_int() because I also wanted to work with double), and a double comparator cmp_dbl(). I added printing functions print_int() and printf_dbl() — renaming your print to print_int. I added memory release function freeBt(). I added code for printBt().
The code playing with the command line arguments allows you to specify a seed of your choosing. It's a bit sloppy; I should probably be using strtoul() instead of atoi(). But it allows you to specify a number on the command line to be used as the seed, which will give you repeatability when you need it. The seed is reported so you can reproduce results. This is helpful when playing with random numbers — sometimes you want randomness, and sometimes you want repeatability.
What I didn't do
I didn't fix the printing code so that the structure of the tree is visible. You just get a list of numbers.
The code doesn't really use the datalen member of the structure, but
it could be useful to check consistency, or for recording the length of strings.

inserting node (Binary search tree) C

I'm trying to insert a node in a binary search tree and I'm getting a little problem.
#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
typedef struct Node{
char name[100];
struct Node *pGauche;
struct Node *pDroit;
}Node;
void getName(char[]);
void copy(Node **, Node *,char[]);
void menu(Node **);
void add(Node **);
void search(char[],Node**, Node **,Node **);
void print(Node **);
void inOrder(Node *);
void main(void)
{
Node *root = NULL;
menu(&root);
system("pause");
}
void menu(Node **root)
{
for (int i=0;i<10;i++)
{
add(root);
}
print(root);
}
void add(Node **root)
{
char name[100];
getName(name);
Node *p = NULL;
Node *savep = NULL;
search(name,root,&p,&savep);
copy(root,savep,name);
}
void search(char name[],Node **root, Node **p, Node **savep)
{
*p = *root;
while ((p == NULL) && (strcmp((*p)->name,name) != 0))
{
*savep = *p;
if (strcmp(name,(*p)->name) < 0)
*p = (*p)->pGauche;
else
*p = (*p)->pDroit;
}
}
void getName(char name[])
{
printf("What name do you want to add\n");
scanf("%s",name);
fflush(stdin);
}
void copy(Node **root, Node *savep, char name[])
{
Node *newp = (Node *) malloc(sizeof(Node*));
newp->pDroit = NULL;
newp->pGauche = NULL;
strcpy(newp->name,name);
printf("%s",newp->name);
if (*root == NULL)
*root = newp;
else
{
if (strcmp(name,savep->name) < 0)
savep->pGauche = newp;
else
savep->pDroit = newp;
}
free(newp);
}
void print(Node ** root)
{
Node *p = *root;
inOrder(p);
}
void inOrder(Node *p)
{
if (p != NULL)
{
inOrder(p->pGauche);
printf("%s\n",p->name);
inOrder(p->pDroit);
}
}
I know there are some really odd function and useless functions, but this just a "test" for a slightly bigger school project so it will get useful in time, right now I would just like to get the binary tree working !
So basically the problem is that I'm getting a "Access violation reading location" after I type in the second name... I'm guessing when doing the strcmp, but I'm really not sure :/
I'd really be glad if someone could help me getting this running :)
A couple of things to get you started. I haven't looked into it too deeply, so you will probably have to continue to drill down into more issues, but fix these things just to get you started:
In this code in search():
while ((p == NULL) && (strcmp((*p)->name,name) != 0))
The p parameter will never be NULL. So, the while loop is never entered. This means that savep would not get set to any value, and is NULL when you call copy() in your add() function. The copy() function then dereferences the invalid pointer reference, which caused the problem you observed.
You actually want to test to see if *p is NOT NULL. This allows you to legally dereference it.
while ((*p != NULL) && (strcmp((*p)->name,name) != 0))
Secondly, as hmjd identified, you do not allocate enough memory for your node inside copy().
Node *newp = (Node *) malloc(sizeof(Node*));
You are only allocating enough memory for one pointer, not for an entire node. Also, you should not cast the return value of malloc() when coding in C (it will hide a bug that can lead to a crash in the worst case).
Node *newp = malloc(sizeof(Node));
Thirdly, you need to retain the memory you allocate for your nodes rather than freeing them immediately after inserting it at the end of copy():
// I need this memory for my tree!
//free(newp);
If you call free() like you did, then your tree will be pointing into freed memory, and to access them would cause undefined behavior.
One minor thing: You shouldn't do fflush(stdin), as fflush() is only for output streams.
This is incorrect:
while ((p == NULL) && (strcmp((*p)->name,name) != 0))
and will result in a NULL pointer being dereferenced, which is undefined behaviour. Change to:
while (*p && strcmp((*p)->name,name) != 0)
This is incorrect:
Node *newp = (Node *) malloc(sizeof(Node*));
as it is only allocating enough for a Node*, when it needs to be allocating a Node. Change to:
Node *newp = malloc(sizeof(*newp));
and don't free() it in the same function as it is required later. free()ing the Node means the list has dangling pointers and dereferencing one is undefined behaviour, and a probable cause of the access violation.
Note:
fflush(stdin);
is undefined behaviour. From the fflush() reference page:
Causes the output file stream to be synchronized with the actual contents of the file. If the given stream is of the input type, then the behavior of the function is undefined.

binary tree: user decides whether it should be a number tree or a word tree in c programming

in my assignment i have to create a binary tree where the user inputs the details.
the first thing the user does is enter 1 if they want to create a number tree or 2 if they want a word tree.
the type of tree they pick is the type it will be for the duration of the running of the program.
there are many functions (and a few structs) that must be written in order to complete the assignment.
my question is how can i write general functions that will work for both int and char?
for example if it is a number tree then the struct for node would include:
int key;
list_t* valueslist;
node* left;
node* right;
but if it was a word list than the struct would look the same except instead of int key it would be char key.
thanks in advance for any help!
The way you may go about it, is to define that data in the struct as a union like so:
struct _Node
{
...
union
{
char* c;
int i;
} data;
};
Than when user makes the choice, access the correct union member according to it.
EDIT
So, let's say the user picked a type, int for instance. And you wish to insert a new value into the tree. (I'll omit error checking fro brevity, but remember to check memory allocation succeeded).
struct _Node* newElem = allocNode();
if (get_user_elected_type() == INT)
newElem->data.i = user_input.i; // Your methods will also need to accept a union
This way has it's serious drawbacks (it's not easy to add a new type, for instance). And most of all it demonstrates how yucky generic programming can be in C. (Using void* can get just as yucky eventually).
There are few solutions to resolve this problem (what you are trying to do is called generic programming)
Use void * key, and fill it with the right data (this is
recommended, because is more generic, but it is also more complicated)
Use a union with 2 fields: an int and a char*
For a homework assignment, the simpler approach will be to use a union type for your data:
struct node {
union {
char *s
int i;
} data;
struct node *left;
struct node *right;
};
and create two sets of functions, one to manage integer values and the other to manage string values:
void insertIntNode(struct node *root, struct node *newNode)
{
if (newNode->data.i < root->data.i)
if (root->left != NULL)
insertIntNode(root->left, newNode);
else
root->left = newNode;
else
if (root->right != NULL)
insertIntNode(root->right, newNode);
else
root->right = newNode;
}
void insertWordNode(struct node *root, struct node *newNode)
{
if (strcmp(root->data.s, newNode->data.s) < 0)
if (root->left != NULL)
insertWordNode(root->left, newNode);
else
root->left = newNode;
else
if (root->right != NULL)
insertWordNode(root->right, newNode);
else
root->right = newNode;
}
bearing in mind you'll need to do some additional memory management for word data:
struct node *createWordNode(char *str)
{
struct node *r = malloc(sizeof *r);
if (r)
{
r->data.s = malloc(strlen(str) + 1);
if (r->s)
strcpy(r->data.s, str);
r->left = r->right = NULL;
}
return r;
}
void destroyWordNode(struct node **n)
{
free((*n)->data.s);
free(*n);
*n = NULL;
}
A more flexible approach is to use a void * to point to your data item, and then delegate all type-aware operations (allocation, assignment, comparison, display, etc.) to other functions which are hidden behind a set of function pointers. For example:
struct node {
void *data;
struct node *left;
struct node *right;
};
struct node *newNode(void *data, void *(*copy)(const void *))
{
struct node *n = malloc(sizeof *n);
if (n)
{
n->left = n->right = NULL;
n->data = copy(data);
}
return n;
}
void insert(struct node *root, struct node *newNode,
int (*compare)(const void *, const void *))
{
if (compare(newNode->data, root->data) < 0)
if (root->left != NULL)
insert(root->left, newNode, compare);
else
root->left = newNode;
else
if (root->right != NULL)
insert(root->right, newNode);
else
root->right = newNode;
}
In the examples above, the details of allocating memory for a node's data element and comparing two data elements are delegated to other functions, and pointers to those functions are passed as parameters to the list management functions. This way you wind up writing a single newNode and insert function, but one that's capable of handling arbitrary node data types. So, for your integer tree, you'd write functions like
void *copyInt(const void *data)
{
const int *src = data;
int *dst = malloc(sizeof *dst);
if (dst)
{
*dst = *src;
}
return dst;
}
int compareInt(const void *lhs, const void *rhs)
{
const int *ilhs = lhs;
const int *irhs = rhs;
if (*ilhs < *irhs)
return -1;
else if (*ilhs == *irhs)
return 0;
else
return 1;
}
then you'd call newNode and insert like
void insertIntValue(struct node *root, int value)
{
struct node *n = newNode(&value, copyInt);
if (n)
insert(root, n, compareInt);
}
The big disadvantage of this approach is that you throw type safety right out the window and into oncoming traffic; because we're using void * for everything. the compiler won't be able to catch type mismatches for us. There's nothing to stop you from passing the wrong copy or comparison function to the generic routines for a particular type.
Which brings us to our second disadvantage - you still need to write a type-aware interface (such as the insertIntValue function above) for each data type you want to support (insertFloatValue, insertStringValue, insertMyObnoxiousDataTypeValue, etc.) along with all of the delegates. Partly to avoid type-safety issues, and partly because our "generic" functions really aren't designed to be called directly. For example, the newNode function expects a pointer as the first parameter, meaning you can't write something like
struct node *n = newNode(10, copyInt);
or
struct node *n = newNode(3.14159, copyDouble);
IOW, you can't pass a literal as the first argument; you must pass the address of an object.
The third main disadvantage is you wind up doing a lot of memory management, which is a pain. You have to create copies of your inputs; otherwise, you wind up assigning the same pointer value (the one passed to newNode) to every node in your tree. Every malloc must have a matching free or you will wind up leaking a lot of memory. You have to be disciplined in how you allocate and deallocate your data items.
Building robust generic containers in C is, frankly, a massive pain in the ass. The only real reason to do it is so you can truly appreciate the value of templates in C++ and generics in Java and C#.

C -- (void*) to int

I'm implementing a simple priority queue in C for a kernel and so I can't use any standard libraries. The queue holds a head node and each node points to the next in the queue.
typedef struct node node;
struct node {
node *next;
void *data;
};
typedef struct {
node *head;
int n;
} queue;
As you can see, each node holds it data in a void*. I'm having trouble converting this data to lets say an int when I pop the data off the stack.
//push data
int int_data = 100;
push(q, &int_data);
//...
//pop data
node* popped = pop(q);
int *pop_data = popped->data;
printf("pop data (100): %d\n", *pop_data);
Why can't I get the original value here? I seem to be printing a pointer value. Alternatively, is there a better way to handle this?
== edit (sorry should have included these):
void push(queue *q, void *data)
{
node new;
new.data = data;
node *new_ptr = &new;
if(is_empty(q))
{
q->head = new_ptr;
q->n++;
return;
}
int i;
node *curr = q->head;
for(i=0; i<q->n; i++)
{
curr = curr->next;
}
curr->next = new_ptr;
q->n++;
}
node* pop(queue *q)
{
node *curr = q->head;
q->head = curr->next;
return curr;
}
Is your code all in one function? If not, int int_data is getting popped off the stack (not your queue, the actual stack) which is probably why you are printing garbage; you are storing the address of a local variable.
I would suggest changing void* data to int data. (If you need to, you can store an address in an int and can cast it back to a pointer later.)
int int_data = 100;
push(q, int_data);
node* n = pop(q);
int num = n->data;
After reviewing your code again, you have the same problem when adding a new node. node new falls out of scope at the end of the function, so basically all of your nodes in your queue are pointing to invalid memory.
If the "pop" operation is in a different function:
The problem is likely because you're pushing a local variable into your queue.
When you go to pop, this address is no longer valid (or at least not pointing to an int value), so you're printing something strange. As the data is no longer pointing to your int, it probably looks like a memory address.
You can use the glib GPOINTER_TO_INT macro:
#define GPOINTER_TO_INT(p) ((gint) (glong) (p))
But please, take note with the doc note:
YOU MAY NOT STORE POINTERS IN
INTEGERS. THIS IS NOT PORTABLE IN ANY
WAY SHAPE OR FORM. These macros ONLY
allow storing integers in pointers,
and only preserve 32 bits of the
integer; values outside the range of a
32-bit integer will be mangled.
are you setting data = int_data (i.e. int --> void*) or data = &int_data (i.e. int* --> void *) ? In the former case, you have to write printf("pop data (100): %d\n", pop_data);

Resources