This is a structure that I am using:
struct nodeList//a node structure
{
int jump;
int config;
int level;
int shifts[200];
int shift_diff[200];
struct nodeList *next;
};
I want to create a 2D array of pointers that can be used to reference such a structure variable, ie, any element of that array can be assigned a pointer to a structure variable. I would prefer to create the array dynamically using malloc, if possible. Any pointers (pun unintended) would be appreciated.
First of all, please think twice about the program design. Do you really need a 2D array of pointers, each pointing to a struct, each struct containing a number of items? Those requirements are rather complex: if you can simplify them, your program will turn out much better.
Because with the current requirements, you'll notice that the pointer and array syntax will turn quite complex, which the requirements are to blame for, more so than the C language.
Consider things like using a 2D array of structs, or to use some sort of pointer-based ADT which makes sense for your given case (linked list, queue, graph, binary tree? etc etc).
That being said, a 2D array of pointers to struct:
struct nodelist* array[X][Y];
To allocate this dynamically, you need a pointer to a 2D array of pointers to struct:
struct nodelist* (*array_ptr)[X][Y];
Then assign this to a 2D array of pointers to struct, allocated dynamically:
array_ptr = malloc( sizeof(struct nodelist*[X][Y]) );
...
free(array_ptr);
Note that unless the 2D array is not allocated like above, in adjacent memory cells, it is not an array.
EDIT. Btw, if you wish to avoid the weird syntax that an array pointer will yield, there is a trick. With the code above you will have to address the array as
(*array_ptr)[i][j];
Meaning: "in the 2D array, give me item number [i][j]".
Had you omitted the inner-most dimension of the type, you could simplify this syntax:
struct nodelist* (*array_ptr)[Y]; // pointer to a 1D array
The malloc will be the same but you can now use it like this instead, which may be more intuitive:
array_ptr[i][j];
Meaning: "in array number i, give me item number j". You are here assuming there is an array of arrays in adjacent memory, which is true.
NODELIST ***pppNode, Node;
size_t Row = 5, Col = 5, i;
pppNode = malloc( sizeof(NODELIST **) * Row );
for(i = 0; i < Row; i++)
pppNode[i] = malloc( sizeof(NODELIST *) * Col );
pppNode[1][0] = &Node;
This is another way of dynamic allocation but as #Lundin said if it is not necessary change the design.
Related
I have a problem with lists and pointers, let me explain.
let's define a list like this:
typedef struct list *LIST;
typedef struct node *link;
struct list{link head; int n;};
struct node{Item val;link next;};
where n is the number of nodes and LIST is a pointer to struct list (I have to do that because I want to make an opaque pointer to the list, in my homework the LIST pointer would go in the .h and the structs would go in the .c but that's not the problem, and I know I should avoid declaring pointer like that).
The Item type is also declared via an opaque pointer, so I have something like this:
typedef struct info *Item;
struct info{char *name;int N};
my problem is that I don't understand how to insert stuff in this lists. (so I would like to add an Item type to the lists, but I can't because Item is a pointer so, for example if a try to do this:
//the lists is already initialized and let's say we want to add 3 nodes
Item x=malloc(sizeof(*x));`
x->name=calloc(10,sizeof(char));
for(int i=0;i<3;i++){
fscanf("%s",x->name);
fscanf("%d",x->N);//this is a random number
ListInsert(L,x);
}
this is what i have in ListInsert():
void ListInsert(LIST L, Item x){
link z,p;
if(L->head==NULL)
L->head=newNode(x,L->head);
else{
for(z=L->head->next, p=L->head;z!=NULL;p=x, z=z->next);//i know a tail would help
p->next=newNode(x,z);
}
}
And this is what I have in newNode():
link newNode(item x,link next){
link z=malloc(sizeof(*z));//should control the allocation was successful I know
z->val=x;
z->next=next;
return z;
}
Whenever I modify the value x, I'm actually modifying what the head and everything points to, that's my problem, what could be a solution? maybe make an array? pointers can sometimes be so hard to understand, for example should I allocate z->val->name?
When you say ...
Whenever I modify the value x, I'm actually modifying what the head and everything points to, that's my problem, what could be a solution?
... I think you're talking about this code:
Item x=malloc(sizeof(*x));`
x->name=calloc(10,sizeof(char));
for(int i=0;i<3;i++){
fscanf("%s",x->name);
fscanf("%d",x->N);//this is a random number
ListInsert(L,x);
}
Indeed, you have allocated only one struct info and assigned x to point to it. You have added that one struct info to your linked list three times, and also modified it several times.
Supposing that your objective is to add three distinct objects to the list, the solution starts with allocating three distinct objects (else where would they come from?). Since each one has a pointer to a dynamically allocated array, you will also want to allocate a separate array for each of those. The easiest way to achieve that would be simply to move the allocations into the loop:
for (int i = 0; i < 3; i++) {
Item x = malloc(sizeof(*x));
x->name = calloc(10, sizeof(char));
fscanf("%s", x->name);
fscanf("%d", x->N); //this is a random number
ListInsert(L, x);
}
If you are permitted to modify the structures involved then you could also consider making the name element of struct info an array of suitable length instead of a pointer. That's a little less flexible, but it would mean that you need only one allocation for each item, not two.
I've got a question about array initialization/usage in C for storing structs.
Suppose I have a Person struct:
struct person {
char *name;
int age;
};
and I declare an array of person structs:
struct person people[1000];
My question is, given this array at some future point in the program where n struct persons have been added to people[], what is the correct way to tell where to put the n + 1th struct person?
In something like Java a for loop with if(people[i] == null) could tell you if that index was not yet holding any value, but in C because this is an array of actual values I know I can't check if(people[i] == NULL) since NULL is pointer.
Is there a reliable/correct way to do this in C?
Just use a variable to keep track of number of elements in the array.
int people_count = 0;
struct person people[1000];
void add(struct person p) {
people[people_count] = ...
people_count++;
}
In C, arrays cannot have positions that are empty, meaning that all the elements in an array must exist (in Java, you would essentially have array of pointers, whereas in C you have array of values of the size depending on your struct size).
One common solution would be to add id field to your struct that would indicate whether your struct on a particular position of the array has been initialized or not, i.e.:
struct person {
char *name;
int age;
int id; // meaning: is initialized
};
I am assuming you would like to put something in your array not only at the end (in this case the other answers are better) but also is some positions that haven't been initialized for some reason.
There are multiple solutions:
Just store the value of n and update it when necessary.
Allocate the items of the people array on the HEAP, so the type of the items will be person*. Then you can check for null pointers and it is also more memory friendly, as you do not have to store unnecessary elements. However, for computation performance, I would still not recommend to find the first empty array element with a a linear search, instead store the index of the first free item.
For the following declaration of graph (that I cannot change - assignment),
#define TAG(vp) ((vp)->tag)
#define LABEL(vp) ((vp)->label)
#define EDGE(vp) ((vp)->edge)
typedef struct vertex
{
char tag;
char *label;
struct vertex *edge[1];
}
vertex, *vp;
when I allocate memory with the following line
EDGE (test) = (vp *) malloc (sizeof (vp) * 3); // where test is a node of a graph
I get the following error
error: incompatible types when assigning to type ‘struct vertex *[1]’ from type ‘struct vertex **
Also I cannot assign EDGE as NULL. I guess I'm missing something with the declaration (it uses *ptr[1] which is quite confusing me). Can you help?
Thanks in advance.
What you're looking at is pre-C99 code called the "struct hack". In C99 or later, you'd use a flexible array member.
The general idea is that you allocate the structure plus some extra space at the end that you use through the array member:
struct vertex *v = malloc(sizeof *v + n * sizeof(struct vertex *));
To allocate a structure with space for n edges (and a sentinel, as #EricPostpischil mentions below). I didn't use your *vp typedef, since I don't like hiding pointer types via typedef like that.
After that allocation, you can just use the array like normal:
v->edge[0] = &someOtherVertex;
v->edge[1] = &someOtherOtherVertex;
And so on.
If you want just one edge per vertex do:
struct vertex *edge;
Or else you can modify your macros (ug? why?) such as:
#define EDGE(vp) ((vp)->edge[0])
but you probably want the first option, as you seem to be creating the array dynamically.
What you cannot do is to assign to the array itself: either make it a pointer or assign to the (only) element of the array.
Note that the usual idiom in C to create a dynamic array is declaring a plain pointer and make it point to the first element of the dynamic array.
Using the readily available on linux systems program, cdecl I can see what does
struct vertex *edge[1];
mean:
adi#laps:~$ cdecl
Type `help' or `?' for help
cdecl> explain struct vertex *edge[1];
declare edge as array 1 of pointer to struct vertex
cdecl>
Thus your prescribed data structure represents the edges coming out of a vertex as pointers stored in a structure. Because you do not have any count of how many edges there are, you are left to use a sentinel, NULL, to mark the end of the array.
Thus EDGE(vp)[0] is the first coincident vertex, EDGE(vp)[1] is the second, etc., until you read a NULL.
This is called the trailing array idiom and you must remember that sizeof(struct vertex) is the amount of memory needed for a vertex having no edges (only the sentinel) and whenever adding more edges to a vertex, you must make sure that enough memory was allocated for the block holding the struct.
Also, this idiom has been standarized in C99 as the flexible arrays and the difference is you do not declare the size of the array
struct vertex {
struct vertex* edge[];
}
Instead of
EDGE (test) = (vp *) malloc (sizeof (vp) * 3);
you need to do
EDGE (test) = malloc (sizeof (vp)); // to allocate array of pointer to vertex
EDGE (test)[0] = malloc (sizeof (vertex)); // to allocate the vertex itself.
if you cannot change
struct vertex *edge[1];
What's the difference between
struct mystruct *ptr = (struct test *)malloc(n*sizeof(struct test));
and
struct mystruct **ptr = (struct test *)malloc(n*sizeof(struct test *));
They both work fine, I'm just curious about the actual difference between the two. Does the first one allocate an array of structs, whereas the second one an array of struct pointers? The other way around? Also, which one has a smaller memory footprint?
The first allocates an array of struct, and the other allocates an array of pointers to struct. In the first case, you can write to fields by assigning ptr[0].field1 = value; right away, while in the second case you must allocate the struct itself before doing the actual writing.
It is OK to drop the cast of malloc result in C, so you could write
struct mystruct **ptr = malloc(n*sizeof(struct test *));
for (int i = 0; i != n ; i++) {
ptr[i] = malloc(sizeof(struct test));
}
ptr[0]->field1 = value;
...
// Do not forget to free the memory when you are done:
for (int i = 0; i != n ; i++) {
free(ptr[i]);
}
free(ptr);
I'm just curious about the actual difference between the two
The function malloc doesn't deal in structures or pointers. It only understands bytes. So the first allocates enough bytes for n struct test objects, which the second allocates enough space for n struct test * objects.
They both work fine
The way things look, the 2 would be used for wildly different things. For example, in the second case, you'd have to allocate memory for each ptr[i] element.
Also, which one has a smaller memory footprint
You can answer that yourself if you print sizeof(struct test) and sizeof(struct test *). But again, they're different things, with different purposes. Which has a smaller footprint, a tractor or a beetle ?
The first allocates an array of structs. The second allocates an array of pointers to structs (no memory for the structs themselves). So the second is smaller unless of course your struct is also very small like a pointer.
I'm basically trying to create an array of struct pointers. Each of these pointers is supposed to point to another element of the same structure array i.e BLOCKS[2].
This is what I've done so far.
typedef struct bb {
..
..
..
struct bb **successor;
} BLOCK;
BLOCK BLOCKS[10];
struct bb **A = malloc(sizeof(struct bb*)*5); //create an array of pointers of type struct bb, 5 units i.e A[0]->A[4].
BLOCKS[0].successors = A //just assigning
Now......how do I assign the first element of the pointer array, A, to another structure?
I tried:
A[0] = &BLOCKS[6];
It compiles fine but I get a seg fault.
Have you tried this one:
typedef struct bb {
..
..
..
struct bb *successor;
} BLOCK;
BLOCK BLOCKS[10];
struct bb *A = malloc(sizeof(struct bb)*5); //create an array of pointers of
type struct bb, 5 units i.e A[0]->A[4].
BLOCKS[0].successors = A[0];
Because after looking at it quickly I think the ** should render into * and your malloc is reserving memory not for the size of 5 structures but the size of 5 pointers to this structure.
Quote from Question: "I'm basically trying to create an array of struct pointers."
The array of structure pointer should be
BLOCK *ptrBlockArr[10]; //This an array of size 10, which can store 10 pointers to the structure BLOCK
Now, since, these are pointers, you will have allocated memory for each of the elements. This should be done like
for(int i=0; i<10; i++)
{
ptrBlockArr[i] = (BLOCK *)malloc(sizeof(BLOCK));
}
You question also included: "Each of these pointers is supposed to point to another element of the same structure array" . This can be done like
for(int i=0; i<9; i++) // Run the loop till the last but one element
{
ptrBlockArr[i]->successor = ptrBlockArr[i+1];
}
//Assign the last's element's sucessor as the first element. This will make it circular. Check if this is your intention
ptrBlockArr[9]->successor = ptrBlockArr[0]
Please note that in your structure successor is struct bb**, whereas it should be struct bb*.
Also, you can optimize the code to combine the two loops shown by me above into one loop. I'll leave that to you to learn by yourself and implement.