pointer to array and two dimensional array in c - 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).

Related

mallocing array of structs creates too small of an array

I'm a little new to structs in C and I'm having a problem with creating an array to store them. As the title says when I try to malloc out an array of structs my array ends up being too small by quite a large margin.
Here is my struct:
struct Points
{
char file_letter;
char *operation;
int cycle_time;
};
And here is how I'm trying to create the array:
struct Points *meta_data;
meta_data = malloc(number_of_delims * sizeof(struct Points));
number_of_delims is an int representing the number of Points I'm trying to create and therefore the number of elements in my array.
With number_of_delims being 64 I get an array size of about 8.
Note: this is more or less a project for school and I can't use typedef when declaring my struct as the prof. wants each struct explicitly declared as one each time it is used. This may actually be the source of my problem but we'll see!
struct Points *meta_data;
At this point we have a declaration of an object, meta_data that has type struct Points *... and struct Points *, being a pointer type, typically requires 8 bytes on common implementations. This is observable through the following program:
#include <stdio.h>
struct Points;
int main(void) {
struct Points *meta_data;
printf("sizeof meta_data: %zu\n", sizeof meta_data);
}
Remember, the sizeof operator evaluates the size of the type of the expression, which in this case is a pointer. Pointers don't carry size information about the arrays they point into. You need to keep that (i.e. preferably by pairing number_of_delims with meta_data, if you require both values later on).
With number_of_delims being 64 I get an array size of about 8.
No. You get an array size of exactly 64, as you've expected. Your pointer doesn't automatically carry that size information around with it (because you're expected to), so there is no portable way to come to the conclusion that your allocation can store 64 elements. The only way you could come to this conclusion is erroneously (i.e. by attempting to use sizeof, which as I've explained doesn't work as you expect).
As an exercise, what happens if you declare a pointer to an array of 64 struct Points, like so?
struct Points (*foo)[64] = NULL;
For a start, how many elements can NULL contain? What is sizeof foo and sizeof *foo? Do you see what I mean when I say sizeof evaluates the size of the type of an expression?

Pointer to a first structure in an array of structures?

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.

How do arrays work inside a struct?

If I have for example
typedef struct node
{
int numbers[5];
} node;
Whenever I create an instance of such a struct there's gonna be allocation of memory in the stack for the array itself, (in our case 20 bytes for 5 ints(considering ints as 32 bits)), and numbers is gonna be a pointer to the first byte of that buffer. So, I thought that since inside an instance of node, there's gonna be a 20 bytes buffer(for the 5 ints) and a 4 bytes pointer(numbers), sizeof(node) should be 24 bytes. But when I actually print it out is says 20 bytes. Why is this happening? Why is the pointer to the array not taken into account?
I shall be very grateful for any response.
Arrays are not pointers:
int arr[10]:
Amount of memory used is sizeof(int)*10 bytes
The values of arr and &arr are necessarily identical
arr points to a valid memory address, but cannot be set to point to another memory address
int* ptr = malloc(sizeof(int)*10):
Amount of memory used is sizeof(int*) + sizeof(int)*10 bytes
The values of ptr and &ptr are not necessarily identical (in fact, they are mostly different)
ptr can be set to point to both valid and invalid memory addresses, as many times as you will
There is no pointer, just an array. Therefore the struct is of size sizeof( int[5] ) ( plus possible padding ).
The struct node and its member numbersshare the address. If you have a variable of type node or a pointer to that variable, you can access its member.
When you have a variable such as int x; space is set aside for the value. Whenever the identifier x is used, the compiler generates code to access the data in that space in the appropriate manner... there's no need to store a pointer to it to do this (and if there were, wouldn't you need a pointer to that pointer? And a pointer to that? etc.).
When you have an array like int arr[5];, space is set aside the same way, but for 5 ints. When the identifier arr is used, the compiler generates code to access either the relevant array element or give the address of the array (depending on how it's used). The array is not a pointer, and doesn't contain one... but the compiler may use its address instead of its contents in some situations.
An array is said to decay to a pointer to its first element in many situations, but that just means that in those situations the identifier will give its address instead of its contents, much like when you use the address-of operator with a non-array variable. The fact that you can get the address of the int x with &x doesn't mean x contains the address of an int... just that the compiler knows how to figure it out.
Arrays don't work like that. They only allocate space for their elements, but not for a pointer. The "pointer" you are talking about (numbers) is just a placeholder for the address of the array's first element; think of it as a literal, instead of a variable. Therefore, you can not assign a value to it.
int myint;
numbers = &myint;
This won't work, since there is no memory where you could store &myint. numbers will just be converted to an address at compile time.
Size of structure is always defined by the size of its members.
So its really doesn't matter whether members are simply int, char, float or arrary or even structure itself.

what is the "pointer to a pointer" in c language? [duplicate]

This question already has answers here:
How do pointer-to-pointers work in C? (and when might you use them?)
(14 answers)
Closed 9 years ago.
How do you exactly use the operator ** (pointer to a pointer)?
I saw these operator used to declare a variable and is declared by a structure such as
struct name_of_struct **p_strutture;
What does it do exactly? What is the variable created?
How is this equivalent to *ptr[]?
What is its significance?
When is using a pointer to a pointer important in a program?
A pointer to a pointer basically stores the address of another pointer. A variable has a memory location and a pointer variable is used to store this address. Similarly a pointer variable has a memory address and a pointer to a pointer stores such a memory address
The type struct name_of_struct ** is a pointer to a pointer to struct
name_of_struct see for example here:
// strutture is a struct name_of_struct object
struct name_of_struct strutture;
// p1_strutture is a struct name_of_struct * object
struct name_of_struct *p1_strutture = &strutture;
// p_strutture is a struct name_of_struct ** object
struct name_of_struct **p_strutture = &p1_strutture;
The & operator yields a pointer to an object.
If you declare:
char **myPointer;
you get a pointer pointing to a pointer.
Why would you do such a thing?
If you want for example save some characters (text) you could use a two dimensional array, or you could use a pointer to a pointer.
With the two dimensional array the longest word would "assign" your array size (so a very short word would waste memory). With a pointer to a pointer you do not waste memory! So more elegant in this case would be an array of pointers and every pointer inside of that array points to an array of char.
myPointer = calloc(2, sizeof(char*));
char pointer1[] = "hello";
char pointer2[] = "world";
*myPointer = pointer1;
*(myPointer + 1) = pointer2;
The value of *myPointer would give you the address of pointer1.
The value of of *pointer1 would give you 'h'
This would be the same: *( (*myPointer)) and would also have value: 'h'
With: *( (*myPoniter) + 1) you get as value: 'e'
And *( *(myPointer + 1) ) would return: 'w'
A pointer to a pointer stores the address of a pointer variable.A pointer variable is assigned a memory location just like some other variable . The actual data type of the value of all pointers, whether integer, float, character, or otherwise, is the same, a long hexadecimal number that represents a memory address.
But remember that representation of pointer values depends on the platform. They may be simple integral values (as in a flat memory model), or they may be structured values like a page number and an offset (for a segmented model), or they may be something else entirely.

What is happening in scanf() when using the & operator?

I am new to C programming, and have a question about the following couple lines of code. This takes place within the context of a creating a linked list of struct film:
struct film {
char title[TSIZE];
int rating;
struct film * next;
}
int main(void)
{
struct film * head = NULL;
struct film * prev, *current;
char input[TSIZE];
// some code ommitted
strcopy(current->title, input);
puts("Enter your rating <0-10>");
scanf("%d", &current->rating);
}
Basically my question is about the strcopy() and scanf() functions. I notice that with strcopy the first parameter is using the member access operator -> on a pointer to the struct. I believe that the first argument to strcopy is supposed to be a pointer to char, so when using the member access operator, are we getting a direct pointer to title even though title is not declared as a pointer inside the struct?
I am confused about how this contrasts with the scanf() call where we use the & operator to get the address of current->rating. Is scanf() taking the address of the struct pointer then doing member access or is it the address of the structs member 'rating'? Why not just pass in the pointer similarly to strcopy()?
Id imagine there is a difference between doing &current->rating vs &(current->rating)? Is &current->rating the address of a pointer (kind of like a pointer to pointer?).
Thanks in advance.
When you pass an array as a function argument in C, the compiler actually passes a pointer to the first element in the array. arrayVar is the same as &arrayVar[0]. So, the strcopy function's first argument is a pointer to the first element of the character array title in the structure pointed to by current.
When you pass an int to a function, you are simply passing the value of the variable, not a pointer to it. Since scanf requires a pointer that it will store the value in, you have to use & to get a pointer to the variable instead. The second argument to scanf is a pointer to the integer rating in the structure pointed to by current.
are we getting a direct pointer to title even though title is not declared as a pointer inside the struct?
To grasp the answer to this question fully, you need to understand how data is stored in memory.
Basically (to keep this simple), the computer has rows of memory blocks, each part has an address (like a row of houses). A single variable (like char A;) has only one house and is thus a static address. An array of variables (like char Arr[10]) has multiple houses (all in a row) but the array (pointer) itself can only point to one house at a time.
A bit like using a tape. So when you say Array[1] you're really saying 'relative to the first house [0], move down to the next house [1]' (or more technically, the memory address plus the size of the pointer times by how many blocks you want to move past).
Is scanf() taking the address of the struct pointer then doing member access or is it the address of the structs member 'rating'?
It's the address of struct's member, rating. Normally to clarify dereferencing, one would use brackets, so &(current->rating), as opposed to passing current (&current), but generally compilers know what is being dereferenced, although bracketing can help if there's an issue.
Why not just pass in the pointer similarly to strcopy()?
The array techically is a pointer (multiple houses sorta thing), where-as rating has no pointer (one house, not needed). If you had an array of ints then you'd be able to do that.
current->title is already a pointer (the type is char[] ), so you don't need the & operator while current->rating is not a pointer (the type is an int), so you need to get the address of the variable (which is what the & operator is doing here).

Resources