Manipulating pointer to array of pointers - c

Trying to write a C snippet to store and retrieve an array of structure pointers. I have copied my snippet bellow.
What I am trying to do here-
method Xos_get_cb_info_from_handle() should return the pointer to
the base address of the structure localclient.exit_cb. Which seem to
work.
After getting this base address, I would like to index into the array.
As part of this exercise temp1 should store the address of the 0'th index (first element), temp2 should store the address of 1st index (second element).
My observations are: (look at the output at the end of the code)
I get the base address correct here in temp1 which is 0x40300c
However, the next element (index 1) should be 0x403010. This is in fact 0x40301c. It seems like its being incremented by the size of the structure.
What is going on here? As per pointer arithmetic shouldn't C be increment this by size of structure (but by size of the pointer.)
Can anyone help me shade some light on this scenario? Any code change suggestions are welcomed. Thanks!
#include <stdio.h>
#define X_PROCESS_DUMP_CB_MAX 3
typedef struct {
void* cb_func; /* pointer to callback function */
unsigned cb_arg; /* not interpreted by the framework*/
} X_cb_data_t;
typedef struct err_cb_t{
X_cb_data_t Xos_cb;
unsigned short priority;
struct err_cb_t *next;
}Xos_exit_cb_t;
struct Xos_local_client {
int x; //just placeholder
Xos_exit_cb_t *exit_cb[X_PROCESS_DUMP_CB_MAX];
int y; //just placeholder
};
/*static global to this file, init this in main before accessing it*/
static struct Xos_local_client localclient;
int Xos_get_cb_info_from_handle(int client_handle, Xos_exit_cb_t** cb_head)
{
*cb_head = (Xos_exit_cb_t *)&localclient.exit_cb[0];
return 0;
}
int main()
{
int i = 0;
/*init localclient here*/
localclient.x =1;
localclient.y =2;
for(i =0; i< X_PROCESS_DUMP_CB_MAX; i++)
{
Xos_exit_cb_t *exit_cb_p = (Xos_exit_cb_t *)malloc(sizeof(Xos_exit_cb_t));
localclient.exit_cb[i] = exit_cb_p;
printf("&exit_cb_p: %p exit_cb_p: %p\n", (unsigned int)&localclient.exit_cb[i],(unsigned int)exit_cb_p);
}
/*Test code that fails*/
Xos_exit_cb_t** exit_cb_head; /*Pointer to pointer of exit_cb*/
Xos_exit_cb_t **temp1;
Xos_exit_cb_t **temp2;
if (!Xos_get_cb_info_from_handle(3, exit_cb_head)) {
temp1 = &(*exit_cb_head)[0];
temp2 = &(*exit_cb_head)[1];
printf("temp1: %p, temp2: %p\n", temp1, temp2);
}
return 0;
}
/*Output*/
&exit_cb_p: 0x40300c exit_cb_p: 0xd18628
&exit_cb_p: 0x403010 exit_cb_p: 0xd426c0
&exit_cb_p: 0x403014 exit_cb_p: 0xd426d8
exit_cb_head: 0x40300c, temp1: 0x40300c, temp2: 0x40301c

In your for loop
for(i =0; i< X_PROCESS_DUMP_CB_MAX; i++)
{
Xos_exit_cb_t *exit_cb_p = (Xos_exit_cb_t *)malloc(sizeof(Xos_exit_cb_t));
localclient.exit_cb[i] = exit_cb_p;
printf("&exit_cb_p: %p exit_cb_p: %p\n", (unsigned int)&localclient.exit_cb[i],(unsigned int)exit_cb_p);
}
you are iterating the pointer array. So you see an increment according to pointer arithmetic (increment by pointer size)
Now assuming your code here missed the copy paste mentioned in the comment by #reichhart i.e.
Xos_exit_cb_t** exit_cb_head = &(localclient.exit_cb[0]);
temp1 & temp2 (of type Xos_exit_cb_t *) are actual addresses in memory where structure is allocated. Hence, base address of adjacent elements will be separated by size of structure.
Hope that helps.

Related

Int value inside array cell somehow being stored as a separate 2d array address

I've created this struct, and a function that initializes all of the fields within that struct and returns a struct pointer. Within this struct I have one single dimensional array of integers, and a two dimensional array of pointers. However, when initialing and incrementing the value inside the cells inside party->fragment_sizes[I] (single dimensional array), party->fragment_sizes[] also begins to increment (two dimensional array). Party->fragment_sizes[i] goes from NULL (0x0) to (0x10000), (0x2000000) I have no idea how, but it's messing me up pretty badly. I need party_fragments_sizes to remain NULL until allocated (inside another function).
#include <stdio.h>
#include <stdlib.h>
typedef struct LonelyPartyArray
{
int **fragments; // the address of fragments[i] is being set as
int *fragment_sizes; // the value inside fragment_sizes[i]
} LonelyPartyArray;
LonelyPartyArray *createParty(int num_fragments)
{
int i;
// Allocating LonelyPartyArray struct pointer
LonelyPartyArray *party = malloc(sizeof(LonelyPartyArray));
// I am allocating these separately,
// is something going on with how my system is
// allocating space for these arrays?
// Allocating LonelyPartyArray
party->fragments = malloc(sizeof(int *) * num_fragments);
// Allocating LonelyPartyArray fragment size
party->fragment_sizes = malloc(sizeof(int) * num_fragments);
// Initializing party->fragments to NULL (not used) and fragment_sizes to zero
for (i = 0; i < num_fragments; i++)
party->fragments[i] = NULL;
for (i = 0; i < num_fragments; i++)
party->fragment_sizes[i] = 0;
// Party->fragments[I] is not remaining NULL, but is being
// incremented. (I.e., party-fragments[I] increments 0x0,
// 0x10000, 0x20000, 0x30000 etc). This needs to remain NULL.
for (i = 0; i < num_fragments; i++)
{
if (party->fragments[i] != party->fragment_sizes[i])
break;
printf("Why is this happening???? [%d]\n", i);
printf("%p\n, party->fragments[i]);
}
return NULL;
}
int main(void)
{
LonelyPartyArray *party = createParty(3);
return 0;
}
I have no idea how party->fragments[] is being set as the address for party->fragment_sizes[], but I need them to be separate.

I am getting error in the part wherever I have struct countOf *rep

Why I am getting error like, expected identifier before '(' before = token in the line: rep -> current = arr[i]?
typedef struct countOf
{
int current;
int count;
struct countOf *next_ptr;
} countOf;
typedef countOf *rep;
int main()
{
int arr[9];
int count = 10;
rep = (struct countOf*) malloc(count* sizeOf(countOf));
for (i = 0; i < count; i++ )
{
rep -> current = arr[i];
rep = rep->next_ptr;
}
}
typedef countOf *rep;
Here you create rep as an alias for countOf*. This means that rep is a type, not a variable.
Later you do this:
rep = (struct countOf*) malloc(count* sizeOf(countOf));
But as I said, rep is a type, so the compiler complains that you are trying to assign a value to it, which doesn't make any sense.
I think you mean instead to do
countOf* rep = (struct countOf*) malloc(count* sizeOf(countOf));
You should also remove the typedef.
In this line
rep = (struct *countOf) malloc(count* sizeOf(countOf));
there are two errors. The first one is that rep is a type name not an object. The second one is that instead of struct *countOf there should be at least struct countOf *. though this casting is redundant
Pay attention to that if you will rewrite this statement correctly
rep = rep->next_ptr;
substituting the type name for a name of a variable nevertheless this statement will invoke undefined behavior because the data member next_ptr was not initialized.
If you want to have a global pointer then you can write for example
rep head;
or
rep head = NULL;
that is the same.
Hi Your code has many mistakes and loop holes, I will surely give you a better code but first of all I am just marking mistakes in code and just making your code ready to work. Go through all the comments in code and run this on your machine. This is a working code and help you to understand your mistakes.I checked this on turboC.
#include<stdio.h>
#include<conio.h>
#include<malloc.h>
typedef struct countOf
{
int current;
int count;//why??
struct countOf *next_ptr;//why, u r using continuous blocks
}countOfNode;
// typedef make countOfNode as an dataType
countOfNode *rep;
//Now rep is global pointer of type struct countOf
int main()
{
int arr[10];//why 9 while we have 10 count everywhere in code
int count = 10;
int i;
rep = (countOfNode*)malloc(count * sizeof(countOfNode));
printf("Enter 10 values in array if you want to assign value from array structure array");
for (i = 0; i < count; i++ )
{ clrscr();// to not keep useless on screen;
printf("Enter %dth value in array",i+1);
scanf("%d",&arr[i]);
}
for (i = 0; i < count; i++ )
{
/*any value you want to assign to current
but what is arr[i]??? it contains no value
*/
//rep->current = arr[i];
//Currently there is no next pointer
// rep = rep->next_ptr;
//You assign it 10 continuos blocks so what is the use of ptr???
//For pointer dont assign continuos blocks make it dynamic
rep[i].current = arr[i];
}
printf("Data in structure rep");
for(i=0 ; i<count; i++)
{
printf("%dth node have \t%d\n",i+1,rep[i].current);
}
}
Now you may check the below code with few improvements in your code, This one is not the best way, but it will help you to better understand. We can write code in far better way
#include<stdio.h>
#include<conio.h>
#include<malloc.h>
typedef struct countOf
{
int current;
struct countOf *next_ptr;//it keep address of next node
}countOfNode;
countOfNode *rep;
//Now rep is global pointer of type struct countOf we just keep offset(base address in this)
int main()
{
int count = 10;
int i;
countOfNode *tracker, *tmp;
rep = (countOfNode*)malloc(sizeof(countOfNode));//initializing first time
printf("Enter value To store");
scanf("%d",&rep->current);//storing value for first node
rep->next_ptr = NULL;//assigin null becaus there is no next node
tracker = rep; // we move tracker alway, rep will just keep the offset
for(i=1; i<count; i++)//0 already assigned above
{
tmp = (countOfNode*)malloc(sizeof(countOfNode));//initializing current node
printf("Enter value To store");
scanf("%d",&tmp->current);//storing value for first node
tmp->next_ptr = NULL;//assigin null becaus there is no next node
tracker->next_ptr = tmp; // we move tracker alway, rep will just keep the offset
tracker = tmp;//tracker jump to next node
}
printf("Data in structure rep");
tracker = rep;
for(i=0; i<count; i++)//0 already assigned above
{
printf("%d\t",tracker->current);
tracker = tracker->next_ptr;//jump to next
}
getch();
}

Struct passed from pointer shows wrong values

I have a variable struct employee which I initialized on the heap using malloc. I am passing this variable from a pointer using *tmp as shown bellow. The problem is that the values of the variable once passed to the function are wrong. I assume this has to do with the pointer but I can't find the mistake. I guess I am forgeting a basic about pointers. To me, I am passing the variable struct employee pointed by *tmp (and not its address as passing the pointer would do). Can't see what's wrong in there.
If I check the value inside the createEmployee() function or after calling it, they are right, but they are not in isInformationValid(employee e). If I change my code and pass a pointer to the function, everything works all right.
typedef struct employee{
char nom[MAX_NAME_LEN];
char prenom[MAX_NAME_LEN];
unsigned short badge;
unsigned long secret;
time_t lastAccess;
} employee;
typedef struct maillon maillon;
struct maillon{
maillon* next;
maillon* prev;
employee* e;
};
typedef struct e_list{
maillon* m;
} e_list;
[...]
int isInformationsValid(employee e){
int invalidName = (strlen(e.nom) <= 2 || strlen(e.prenom) <= 2); // Problem here
int invalidBadge = (e.badge < 1000 || e.badge > 9999); // Problem here. e.badge taken as "25789" when I input "1010"
if(invalidName) { errno = EPERM; perror("Name length must be > 2"); return -1; }
if(invalidBadge) { errno = EPERM; perror("Badge must be 4 digits"); return -1; }
return 0;
}
employee* createEmployee(){
employee* tmp = calloc(1, sizeof(employee*));
getString("A man needs a last name : ", tmp->nom, MAX_NAME_LEN);
getString("A man needs a first name : ", tmp->prenom, MAX_NAME_LEN);
getDigits("Badge (4 digit) : ", &tmp->badge, "%hu");
getDigits("Secret : ", &tmp->secret, "%lu");
time_t t = time(NULL);
tmp->lastAccess = t;
if(isInformationsValid(*tmp) == -1){ // Passing addr of the struct
return NULL;
}
return tmp;
}
What did I miss? Did I do something wrong in any initialization or am I missing a basic thing about pointers ?
I saw that other questions on stackoverflow has similar questions
The only answers I could reading those other questions was forgotten dynamic allocations on the heap, which is what I think I am doing (maybe the wrong way tho).
EDIT
I was doing it wrong.
You are allocating the size of an employee *, but you should be allocating the size of an employee (or *tmp).

Circular shift a dynamic c array by n elements

I have a queue of set length implemented as a dynamic c array implemented like this:
typedef struct {
float* queue;
int size;
int pointer;
} QueueStruct;
void createQueue(QueueStruct* queueInstance, int size){
queueInstance->queue = malloc(sizeof(float)*size);
queueInstance->size = size;
queueInstance->pointer = 0;
}
void addElementToQueue(QueueStruct* queueInstance,float element){
queueInstance->queue[pointer] = element;
if (queueInstance->pointer == queueInstance.size - 1){
queueInstance->pointer = 0;
} else {
++queueInstance->pointer;
}
}
void freeQueue(QueueStruct* queueInstance){
free(queueInstance->queue);
}
And I want to implement this function:
float* returnQueue(QueueStruct queueInstance){
//I want this function to malloc a new float* and then put the queue in it in the
// correct order, from start to finish, as pointed too by the pointer.
//Im not sure how to do this.
}
Any help would be appreciated.
Edit: Corrected a silly programming mistake - this is a simplified version of what is actually in my program.
Let's see if I got that right.
float* returnQueue(QueueStruct *queueInstance){
int j = 0;
float *ret = malloc(sizeof(float)*queueInstance->size); //Allocates the memory you want.
//Copies the elements from pointer to End into the new buffer (assumes, that the array has been filled at least once, add a marker to make sure)
if(queueInstance->FilledOnce) { //Marker variable, explanation as above.
for(int i = queueInstance->pointer; i < queueInstance->size; ++i, ++j)
ret[j] = queueInstance->queue[i];
}
//Copies the newest elements (from beginning to pointer) into the buffer.
for(int i = 0; i < queueInstance->pointer; ++i, ++j)
ret[j] = queueInstance->queue[i];
return ret; //Returns the code in question.
}
To make this code work, you'd have to add 'FilledOnce' to your struct, and amend your 'Add' Code as follows:
void addElementToQueue(QueueStruct* queueInstance, float element){
queueInstance->queue[queueInstance->pointer] = element;
if (queueInstance->pointer == queueInstance.size - 1){
queueInstance->pointer = 0;
queueInstance->FilledOnce = 1;
} else {
++queueInstance->pointer;
}
}
I also advise you, to reset your variables, once you're done with it.
void freeQueue(QueueStruct* queueInstance){
free(queueInstance->queue); //Frees the queue
queueInstance->queue = NULL; //Nulls the reference
queueInstance->FilledOnce = 0;
queueInstance->pointer = 0;
queueInstance->size = 0;
}
This way, if you reuse the struct, you won't run into the problem of trying to access non-allocated memory. Just be sure to check for those variables.
I hope this helps.
I think you should allocate memory for your struct also.
You have made pointer of struct but forgot to allocate memory for that struct
use QueueStruct queuestruct= malloc(sizeof(Queuestruct))
then when you pass this to any of the function above then you can easily allocate
memory for queue poiter in which you can store element for your queue array
This implementation is insufficient. A pointer variable give us location of a tail of queue, but what points to it's head?

C - Passing a Pointer to a Function and then Passing that Same Pointer Inside the Function to Another Function

Whew! Long title...here's some pseudo-code to explain that verbiage:
int main(){
int* ptr = function1(); //the data that ptr points to is correct here
function2(ptr);
}
int function2(int* ptr){
//the data that ptr points to is still correct
int i;
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++); //since ptr points to a contiguous block of memory
function3(ptr);
}
int function3(int* ptr){
//the data that ptr points to is INCORRECT!!!
}
Why would the data in function3 be incorrect?
Note: function1 performs a malloc() and returns the pointer to that memory.
ACTUAL CODE
#include <stdlib.h>
#include <stdio.h>
//Structures
struct hash_table_data_
{
int key, data;
struct hash_table_data_ *next, *prev;
};
struct hash_table_
{
int num_entries;
struct hash_table_data_ **entries;
};
typedef struct hash_table_data_ hash_table_data;
typedef struct hash_table_ hash_table;
//Prototypes
hash_table *new_hash_table(int num_entries);
int hash_table_add(hash_table *ht, int key, int data);
int hash_table_loader(hash_table* ht);
//Main
int main()
{
int num_entries = 8;//THIS MUST BE AUTOMATED
hash_table* ht = new_hash_table(num_entries);
hash_table_loader(ht);
return 0;
}
//Function Definitions
hash_table *new_hash_table(int num_entries)
{
hash_table* ht = (hash_table*) malloc(sizeof(hash_table));
hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));
int i;
for (i=0;i<num_entries;i++)
{
array[i].key = -1;
array[i].data = -1;
array[i].next = NULL;
array[i].prev = NULL;
}
ht->entries = &array;
ht->num_entries = num_entries;
return ht;
}
int hash_table_add(hash_table *ht, int key, int data)
{
//VERIFY THAT THE VALUE ISN'T ALREADY IN THE TABLE!!!!!!!!!!!
int num_entries = ht->num_entries;
hash_table_data* array = *(ht->entries); //array elements are the LL base
int hash_val = key%num_entries;
printf("adding an element now...\n");
printf("current key: %d\n", array[hash_val].key);
int i;
for(i=0;i<num_entries;printf("%d\n", (*(ht->entries))[i].key),i++);//DATA IS INCORRECT!!!!
if (array[hash_val].key == -1)//is this the base link?
{
printf("added a new base link!\n");
array[hash_val].key = key;
array[hash_val].data = data;
array[hash_val].next = NULL;
array[hash_val].prev = &(array[hash_val]);
}
else//since it's not the base link...do stuff
{
hash_table_data* new_link = malloc(sizeof(hash_table_data));
new_link->key = key;//set the key value
new_link->data = data;//set the data value
if (array[hash_val].next == NULL)//we must have the second link
{
printf("added a new second link!\n");
new_link->prev = &(array[hash_val]); //set the new link's previous to be the base link
array[hash_val].next = new_link; //set the first link's next
}
else//we have the 3rd or greater link
{
printf("added a new 3rd or greater link!\n");
hash_table_data next_link_val = *(array[hash_val].next);
while (next_link_val.next != NULL)//follow the links until we reach the last link
{
next_link_val = *(next_link_val.next);//follow the current link to the next
}
//now that we've reached the last link, link it to the new_link
next_link_val.next = new_link; //link the last link to the new link
new_link->prev = &(next_link_val); //link the new link to the last link
}
}
return 0;
}
int hash_table_loader(hash_table* ht)
{
int i;
for(i=0;i<(ht->num_entries);printf("%d\n", (*(ht->entries))[i].key),i++); //DATA IS STILL CORRECT HERE
FILE *infile;
infile = fopen("input.txt", "r");
while(!feof(infile))
{
int key,data;
fscanf(infile, "%d %d", &key, &data);
hash_table_add(ht, key, data);
}
fclose(infile);
}
Note: Issue occurring the first time hash_table_add() is called.
Your first problem is here:
ht->entries = &array;
You cause the structure to hold a hash_table_data** which points to the variable hash_table_data* array which is local to the function; then you exit the function and return a pointer to the structure. The structure still exists (it was allocated via malloc(), and the stuff that array points to still exists, but array itself does not. Accordingly, this pointer within the structure is now invalid.
As far as I can tell, there is no reason for you to be holding a pointer-to-pointer here. Just use hash_table_data* as the entries type, and copy array into that struct member. Pointers are values too.
I guess you iterate incorrectly
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++);
this is nonsense.
You should rewrite it as this:
for(i=0;i<length;i++)
printf("%d\n", ptr[i]);
(*ptr)[i] is just wrong, it doesn't make sense if you think about it.
*ptr is the first element of the pointed-to array of ints.
ptr[i] is thi ith one, this is what you need.
Please, read Section 6 carefully.
A couple of advises based on this question:
Don't write overcomplicated code like this for statement with comma operator used, it just rarely needed and leads not only to confusion, but to mistakes (although no mistakes with it in this particular example)
Look carefully for mistakes, don't blame everything on functions. If your code doesn't work, try finding the exact place which is wrong and prove it. In this example people who tested your code were right: functions are definitely not the cause of the error.
hash_table *new_hash_table(int num_entries)
{
hash_table* ht = (hash_table*) malloc(sizeof(hash_table));
hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));
// ....
ht->entries = &array; // Problem
// ...
return ht;
} // Life time of array ends at this point.
You are taking the reference of the local variable array and assigning it to ht->entries which is no more valid once the function returns.

Resources