Pointer to a first structure in an array of structures? - c

I have a function that is supposed to be creating structures and storing them in an array of structures.
Lets say this is my structure:
struct str {
...
};
The function takes a parameter that looks like this:
struct str **ptr
Which is a pointer to a pointer that points to a structure if I get it right and I am supposed to set this parameter to be pointing to the first element of the array of structures which will be the first structure in that array.
So, if the parameter looks like this, that means that instead of having just an array of structures, I have an array of pointers that point to that structure, right?
Now I have declared the array of pointers to structures like this:
struct str *structures[20];
because I am expecting to have 20 (pointers to )structures store there.
Then I have a loop that is allocating memory for the structures and is storing them in the array like this:
struct str *structure;
structure = malloc(sizeof(struct str));
Then I fill in the parameters of the structure I want like this:
structure->a = 1; structure->b = 2; .........
And I store it in the array like this:
structures[n] = structure;
And I make sure it is stored in the array at the position where I wanted it to be by printing a parameter from the structure each loop like this:
printf("%d\n", structures[7]->a);
My question is, how do I set the parameter of the function to be pointing to the first pointer to a structure in that array?
And did I get it right?
Also, the parameter needs to be taken from main.
And I need to work with these (pointers to)structures of the array outside this one function as well.
What will the parameter look like?
struct str *pointer; ?
Also, wouldn't it be possible to just point the pointer to the array itself and it should automatically be pointing to the first element in it?
So that I could then reference the nth member of the array via the pointer since I need to work with all of them later on?
I have looked at this thread, but I'm still a bit confused so I'd appreciate any feedback.

Reading through this, I notice a few inconsistencies in your post:
Why create an array of pointers to your struct as opposed to a simple array of structs? That is, let's say you have this declaration for your struct:
struct myStruct {
int x;
int y;
};
If you want to create an array of those structs just do:
//dynamic
struct myStruct* myArray = malloc(20*sizeof(struct myStruct));
//static
struct myStruct* myArray[20];
Note that both of these return a pointer to the first element of the array (which is of type struct myStruct). Your array is an array of struct myStruct elements, not an array of struct myStruct*.
An array of struct myStruct elements with size 20 is, for practical purposes, nothing more than contiguous memory big enough to hold 20 struct myStruct elements and represented by the pointer to the first element. Since the memory is contiguous, you can access the 'nth' element of your array by myArray[0] or *(myArray+n) (the latter is possible because an "array" is nothing more than a pointer to the first element of contiguous memory... so "adding" 1 to a pointer of a given type gives you the memory address of the next element... which you deference using the * operator to get the element itself).
It'll be much easier (not to mention much faster) to allocate memory for your array of structs once rather than creating an array of pointers to your structs. And then modify them in place.
So a function that takes in the array and increments that 5th and 6th elements might look like:
void modifyStructs (struct myStruct* myArray)
{
//modify the fifth struct:
++myArray[4].x;
//modify the sixth struct:
++myArray[5].x;
}
The few times you'll want an array of pointers are when:
Creating a multidimensional array. Even then, this is really bad for cache performance... it's better to create a 1D array and define a macro for how to access the elements. BLAS/LAPACK do this.
Creating an array where some elements should be NULL and you're not using structs. If you're using structs, it's much better to just define a field to identify whether your struct has been populated yet and use a simple array of structs.
Creating an array to access a huge number of items but you don't want to allocate all that memory yet. Here, you don't really have a choice.

Related

dynamically allocate 2d array of structs in C

(corrected the code after a few good comments pointing out some mistakes in the previous version of the code)
If I'm right, the best way to dynamically allocate a 2D array of structs in C is the following:
struct xx(*array2d)[y] = malloc(sizeof(struct xx[x][y]));
Does it make any difference whether I store the structs in the array or store pointers to them?
I was also wondering if I may simply deallocate the allocated memory in the following way:
void free2d(int x, int y, struct xx array2d[x][y]) {
free(array2d);
}
Identifiers in C cannot begin with numbers so 2darray won't work.
Formally, the most correct way to allocated a 2D array dynamically is:
struct xx (*array)[x][y] = malloc(sizeof(struct xx[x][y]));
However that makes accessing the array cumbersome, because we would have to de-reference the array pointer first:
(*array)[i][j]
A common trick to avoid this is to have the array pointer not point at the "whole" 2D array, but to the first item. Which would be a struct xx [y] array in this case.
So we can use a pointer to the first element but still allocate the correct amount:
struct xx (*array)[y] = malloc(sizeof(struct xx[x][y]));
And now we can use this as
array[i][j]
In either of the two examples above, you free it with a single free(array) call.
The allocation code is a bit incorrect.
variable name cannot start with a digit, thus identifier 2darray is illegal. Use array2d instead
memory allocation code look almost correct. Note that array2d would be a pointer to array of x elements of type struct xx. Thus the correct allocation code swap order of x and y in sizeof expression.
struct xx (*array2d)[x] = malloc(sizeof(struct xx[y][x]));
If you want x be the first dimensions use:
struct xx (*array2d)[y] = malloc(sizeof(struct xx[x][y]));
Personally I prefer to use the following pattern because it is less error prone:
struct xx (*array2d)[x] = calloc(y, sizeof *array2d);
Passing to function. It is simple, just pass array dimensions as arguments and then the array itself.
void foo(int x, int y, struct xx array2d[static x][y]) {
Note that parameter array2d is actually a pointer to array. The "static extent" tells the compiler that at least x elements pointer by the pointer are valid. It is very useful for documentation. Moreover static makes the declaration visually distinct from a declaration of an array.
Deallocation. The free2d function could be used if it followed the pattern from point 2. However I recommend simply using free(array2d);
I would use objects instead of types.
struct xx(*array2d)[cols] = malloc(rows *sizeof(*array2D));
To deallocate you do not need sizes only void pointer to your array
void free2d(void *array2d) {
free(array2d);
}
or simple use free with your pointer to the array.

pointer to array and two dimensional array in c

struct packet_event *packet_event_p[8];
What does this mean ? Is it a pointer to an array of structure data type (struct packet_event) that has 8 elements ? And how could I make use of this pointer ?
Is it different from :
struct packet_event **packet_event_p;
If yes, how could I use this pointer ?
The first one:
struct packet_event *packet_event_p[8];
stands for 'declare packet_event_p as an array of 8 pointers to struct packet_event'. Thus, you create an array packet_event_p of 8 elements, which are pointers to the struct packet_event. Please see this link.
whereas the second one:
struct packet_event **packet_event_p;
stands for 'declare packet_event_p as pointer to pointer to struct packet_event'. Please see this link.
Hope this is helpful.
The first declaration :
struct packet_event *packet_event_p[8];
defines an array of 8 elements, each element of which is a pointer to struct packet_event . In other words, you have an array of 8 pointers, and each one points to a struct packet_event.
And how could I make use of this pointer ?
You can allocate memory for a struct packet_event and set a pointer of your array point to it, like this :
struct packet_event *ptr = malloc(sizeof(struct packet_event));
if (ptr == NULL)
printf ("Error\n");
else
packet_event_p[0] = ptr; //choose a pointer packet_event_p[0] - packet_event_p[7]
The second declaration :
struct packet_event **packet_event_p;
is different, as you declare a pointer (and not an array), named packet_event_p, which points to a pointer to struct packet_event.
If yes, how could I use this pointer ?
Allocate memory for the double pointer packet_event_p. See this link for allocating memory for double pointers.
It is true that arrays can be decayed to pointers, but they are not the same.
regarding the type it is "Array of 8 pointers to a struct of packed event"
reading the types in C usually goes in some sort of a whirlwind fashion. To properly to do, you can read this here.
Usually when you are passing this type as function argument, you will also add the size of the array, or use an external known variable to mark its length. Usually function declarations will be pointers instead of arrays type. I think even that the compiler does automatically (comments about that will be useful)
One different between those types can be seen using the sizeof operator. when applied on variable which is known to be an array type, then the result is the entire size of the array. Otherwise it will be a size of a pointer, which might be 4 byte or 8 byte (depending if its a 64/32bit machine).

What is the difference between struct node**hashTable and struct node*hashTable[MAXSIZE]?

I am having a bit of trouble understanding the difference between these two.. are both of these a pointer to a pointer?? and also, what are the appropriate cases in which each of them would be ideal to use??
struct node *hash1[MAXSIZE];
struct node **hash2 = hash1;
The first creates an array of MAXSIZE elements, but each element is a pointer to a struct node.
The second creates a single variable, a pointer to a pointer, which is initialized with the address of the zeroth pointer in the hash1.
You might use the second notation in the parameter list of a function, or when you need a single reference to an entire hash table. You use the first when you lay out memory, creating a hash table which can be modified later.
The first is a pointer to pointer to struct node, the second is an array of MAXSIZE pointers to struct node.
Use the C operator precedence rules to untangle the types.

relationship between pointers and arrays

My question is both specific to an assignment I'm working on and conceptual about the relationship between pointers and arrays. I'm writing a hash table in the form of an array of pointers to sorted lists. I've created a struct to define a type for the hash table and the number of elements in the table is defined in a macro. Since the size of the table is variable, the struct needs to contain a pointer to the table itself - a pointer to an array of pointers. My problem revolves around the idea that a pointer to some data type is the same as the label for the first element of an array of that data type.
I have a data type SortedList. As I understand things, SortedList* can be interpreted as either a pointer to a single SortedList or as a pointer to the first element of an array of SortedList's. Expanding on that, SortedList** can be an array of SortedList pointers and SortedList*** can be a pointer to that array. This is what I have in my hash table struct. My first question is, is my understanding of this correct?
In the function that creates the hash table I have this:
SortedList** array;
if ((array = calloc(size,sizeof(SortedList*))) == NULL) {
// error allocating memory
printf("Memory Error\n");
return NULL;
}
table->arrayPtr = &array;
So array is intended to be my array of SortedList pointers and arrayPtr is the SortedList*** type in my hash table struct. I'm using calloc because I think it will initialize all of my pointers to NULL. Please let me know if I'm mistaken about that. This all compiles with no errors so, as far as I know, so far
so good.
I have function that inserts data into the table that first checks to see if this pointer has not been used already by checking to see if it points to NULL, if not, it creates a SortedList for it to point to.
int i = index->hashFunc(word);
SortedList*** table = index->arrayPtr;
if (*(table +i) == NULL){
return 0;
}
So it seems to me that dereferencing (table +i) ought to give me a SortedList** - the ith element in an array of SortedList pointers - which I can then check to see if it's set to NULL. Unfortunately, the compiler disagrees. I get this error:
error: invalid operands to binary == (have ‘struct SortedList’ and ‘void *’)
So somewhere along the line my reasoning about all this is wrong.
You might need to read up a little bit more on arrays and pointers in C because I don't think you completely grasp the concept. I could be wrong but I doubt you'd need a three level pointer to achieve what you're trying to do; I think you might be confusing yourself and thinking that if you want to point to an array's data you need to point to the actual array (&array), which is essentially a pointer itself. Drawing a picture can also really help to visualise what's going on in memory.
An array is merely a block of sequential data, where the variable's name in C (without any [ ], which would get an element from the array) points to the first element in the array. The two lines in the example below are equivalent (where array is obviously an array):
int *p_array;
p_array = array; /* equivalent */
p_array = &array[0]; /* equivalent */
You could then use p_array exactly the same way as if you were to use array, ie.
p_array[3] == array[3]
The unnecessary thing that some people might do when they're learning is have a pointer to a pointer to an array (which I think is what you're doing):
int **p_p_array = &array;
And then to access the elements of array they would have to dereference the pointer and then use array notation to specify the element in the array:
*p_p_array[3] == array[3]
What we've actually done here is store the memory address of array (which itself is a pointer to the first element), which we then have to dereference to get to the first element, and then we move 3 positions forward to get to the fourth element (array[3]).
In the first example it's so much simpler and more logical, since we're storing a pointer to the first element in the array and having the pointer act in the same way as our initial array variable.
I recommend you draw out what you're trying to do on a piece of paper/whiteboard to see what you're doing wrong and it may then become obvious how to properly implement it the right way. My whiteboard is one of my best tools when I'm coding something.

Initialization of Array inside a Structure in C

I'm trying to allow a variable length array inside a struct in a C program. Something like this:
struct result{
int column;
int row;
const char* a[var][var];
};
how do i do this?
even the following definition would do:
struct result{
int column;
int row;
const char* a[row][column];
};
plese do help...
You can't have variable size arrays in C structs.
You can have pointers to arrays which can be variable size (you need to handle the allocation of the space separately), but you are declaring arrays of pointers instead
If you want an array of pointers, try
const char (*a)[][];
(you'll need to manage the array as an array of pointers to arrays if you want both dimensions to be variable)
Just use pointers instead. You'll have to do dynamic memory allocation. Don't forget to free() the memory allocated for your array :)
P.S.: If you need a 2-dimensional array, use a pointer-to-pointer (that is, allocate memory for an array of pointers)
For single-dimension arrays you can do something like this:
struct TEST {
...
int size;
char string[];
}
where the size field indicates how many characters there are in the string array. The array has to be the last member of the struct, and you have to allocate the struct's memory dynamically. The allocated size should be sizeof(struct TEST) + size * sizeof(char) in this case.
You cannot have more than one variable size array in the struct. Multi-dimension variable-size arrays are trickier. It cannot be done unless only one dimension size is unknown, specifically that of the first dimension.
struct TEST {
...
int size;
char string[][100];
}
EDIT:
As other posters mentioned, you can have pointers to one or more arrays, at the cost of having to manage their memory areas separately from the struct.
EDIT 2:
This is part of at least the ISO C99 standard. Shamelessly copying from paragraph 6.7.2.1, sub-paragraph 16:
16 As a special case, the last element
of a structure with more than one
named member may have an incomplete
array type; this is called a flexible
array member. With two exceptions,
the flexible array member is ignored.
First, the size of the structure shall
be equal to the offset of the last
element of an otherwise identical
structure that replaces the flexible
array member with an array of
unspecified length.106)...
Use dynamic allocation with the malloc function.
In your case you should do something like:
#include <stdlib.h> /* header file for the malloc function */
void allocateResult(struct result* res, int row, int column) {
res->a = (const char*) malloc(row * column * sizeof(char));
}
Please note that sizeof(char) equals to 1 (almost all the time), but for other types you'd have to do it this way.
This solution implies to free allocated memory before the program ends. You'll have to pass the pointer in your struct to free:
void freeResult(struct result* res) {
free(res->a);
}

Resources