Struct pointer syntax confusion - c

Hi i'm relatively new to c and was wondering if anyone could explain what exactly i'm doing with the following code.
I have a struct:
typedef struct free_list_header {
u_int32_t magic; // ought to contain MAGIC_FREE
vsize_t size; // # bytes in this block (including header)
vlink_t next; // memory[] index of next free block
vlink_t prev; // memory[] index of previous free block
} free_header_t;
and I'm initialising it within a function using the following...
void vlad_init(u_int32_t size)
{
int sizePow2 = pow(2, ceil(log(size)/log(2)));
memory = malloc(sizePow2*sizeof(char));
memory_size = sizePow2;
strategy = BEST_FIT;
free_header_t *freeHeader = (free_header_t*)memory;
freeHeader->magic = MAGIC_FREE; // the unique value
freeHeader->size = memory_size; // amount we malloc'd
freeHeader->next = 0; // position of next free block
freeHeader->prev = 0; // position of prev free block
free_list_ptr = 0;
}
my question is what exactly am i doing here and why is it necessary?
free_header_t *freeHeader = (free_header_t*)memory;
So... i'm declaring a new struct by pointing to it named "freeHeader"? and that is a pointer to it in the memory i have allocated? So this is a way of putting the struct into the malloc'd area to access it out of the function in which im initializing it?

Malloc returns a void pointer (type void*). This means it returns a pointer to a memory address and that pointer is not pointing to any specific type. So after the line:
memory = malloc(sizePow2*sizeof(char)); //sizePow2 is n bytes to allocate
memory is a pointer of type (void *).
free_header_t *freeHeader = (free_header_t*)memory;
On the left hand side here you are creating a pointer named freeHeader that points to a memory address containing something of type free_header_t
Since you explicitly said this pointer is pointing to an address of type free_header_t to you are casting the other side (currently of type void *) to match it as free_header_t *.
NOTE in C, this works but is not necessary. The compiler will automatically cast a void * to whatever type you need. However writing code like this is good practice, in C++ you need to explicitly do this.

free_header_t * freeHeader = (free_header_t*)memory;
you declared a pointer (not an actual struct) to free_header_t struct named freeHeader and you assigned it the value of the pointer named memory. since memory is a pointer to char and yours is a pointer to something else, you used casting.
You currently have only a pointer to an allocated area (of size sizePow2*sizeof(char) - note that the size of the struct should be less or equal to the size of the allocated memory).

Your code is essentially equivalent to:
free_header_t *freeHeader = malloc(sizePow2 * sizeof(char));
It's allocating a block of memory that contains sizePow2 bytes, and then using that as the address of a free_list_header structure.
The reason it uses the memory variable is because some other code is going to use the next and prev members as indexes into that block of memory. As the name implies, this structure just contains the data at the beginning of the memory block, the rest of the memory is managed with other structures.

memory = malloc(sizePow2*sizeof(char));
You are allocating some memory here. It would be good to just use
memory = malloc(sizeof(struct free_list_header));
to store an object of the structure.
free_header_t *freeHeader = (free_header_t*)memory;
Here you are declaring a pointer which would point to memory allocated earlier. You did not technically declare an object of the structure. And you are not putting the structure in to malloc-ed area, you are instead treating the malloc-ed area as an object of the structure.
free_header_t freeHeader = {0}; would be declaring an object of the structure.

Every time you call malloc() function, the operating system returns you a single memory address. When you cast this pointer to a specific type you tell to compiler that every element stored in the memory allocated will consume the size of the specified type and this get the things easier.
Let suppose that you declare a uint64_t* and the size of allocation it's 100 times the size of uint64_t, so you're asking for 800 bytes for the operating system, once the uint64_t takes 8 bytes. If you do not cast this pointer, every time you increase the address with your_variable++ your program will skip only one byte and you will get in the "middle of the number and will get a weird value", but if you cast your pointer to a uint64_t and increase the address with your_variable++ your program will skip 8 bytes, going directly to the next number.
In your example, you're telling to the operating system that your pointer will store types of free_header_t. You're not obligated to do it, but it is a very good practice.
And yes, if you return this address to another function, the other function can change the value stored in this memory area easily.
Hope it helps!

Related

Difference in creating a struct using malloc and without malloc

Could someone please explain to me the difference between creating a structure with and without malloc. When should malloc be used and when should the regular initialization be used?
For example:
struct person {
char* name;
};
struct person p = {.name="apple"};
struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";
What is really the difference between the two? When would one approach be used over others?
Having a data structure like;
struct myStruct {
int a;
char *b;
};
struct myStruct p; // alternative 1
struct myStruct *q = malloc(sizeof(struct myStruct)); // alternative 2
Alternative 1: Allocates a myStruct width of memory space on stack and hands back to you the memory address of the struct (i.e., &p gives you the first byte address of the struct). If it is declared in a function, its life ends when the function exits (i.e. if function gets out of the scope, you can't reach it).
Alternative 2: Allocates a myStruct width of memory space on heap and a pointer width of memory space of type (struct myStruct*) on stack. The pointer value on the stack gets assigned the value of the memory address of the struct (which is on the heap) and this pointer address (not the actual structs address) is handed back to you. It's life time never ends until you use free(q).
In the latter case, say, myStruct sits on memory address 0xabcd0000 and q sits on memory address 0xdddd0000; then, the pointer value on memory address 0xdddd0000 is assigned as 0xabcd0000 and this is returned back to you.
printf("%p\n", &p); // will print "0xabcd0000" (the address of struct)
printf("%p\n", q); // will print "0xabcd0000" (the address of struct)
printf("%p\n", &q); // will print "0xdddd0000" (the address of pointer)
Addressing the second part of your; when to use which:
If this struct is in a function and you need to use it after the function exits, you need to malloc it. You can use the value of the struct by returning the pointer, like: return q;.
If this struct is temporary and you do not need its value after, you do not need to malloc memory.
Usage with an example:
struct myStruct {
int a;
char *b;
};
struct myStruct *foo() {
struct myStruct p;
p.a = 5;
return &p; // after this point, it's out of scope; possible warning
}
struct myStruct *bar() {
struct myStruct *q = malloc(sizeof(struct myStruct));
q->a = 5;
return q;
}
int main() {
struct myStruct *pMain = foo();
// memory is allocated in foo. p.a was assigned as '5'.
// a memory address is returned.
// but be careful!!!
// memory is susceptible to be overwritten.
// it is out of your control.
struct myStruct *qMain = bar();
// memory is allocated in bar. q->a was assigned as '5'.
// a memory address is returned.
// memory is *not* susceptible to be overwritten
// until you use 'free(qMain);'
}
If we assume both examples occur inside a function, then in:
struct person p = {.name="apple"};
the C implementation automatically allocates memory for p and releases it when execution of the function ends (or, if the statement is inside a block nested in the function, when execution of that block ends). This is useful when:
You are working with objects of modest size. (For big objects, using many kibibytes of memory, malloc may be better. The thresholds vary depending on circumstances.)
You are working with a small number of objects at one time.
In:
struct person* p_tr = malloc(sizeof(struct person));
p_tr->name = "apple";
the program explicitly requests memory for an object, and the program generally should release that memory with free when it is done with the object. This is useful when:
The object must be returned to the caller of the function. An automatic object, as used above, will cease to exist (in the C model of computation; the actual memory in your computer does not stop existing—rather it is merely no longer reserved for use for the object) when execution of the function ends, but this allocated object will continue to exist until the program frees it (or ends execution).
The object is very large. (Generally, C implementations provide more memory for allocation by malloc than they do for automatic objects.)
The program will create a variable number of such objects, depending on circumstances, such as creating linked lists, trees, or other structures from input whose size is not known before it is read.
Note that struct person p = {.name="apple"}; initializes the name member with "apple" and initializes all other members to zero. However, the code that uses malloc and assigns to p_tr->name does not initialize the other members.
If struct person p = {.name="apple"}; appears outside of a function, then it creates an object with static storage duration. It will exist for the duration of program execution.
Instead of struct person* p_tr = malloc(sizeof(struct person));, it is preferable to use struct person *p_tr = malloc(sizeof *p_tr);. With the former, a change to the p_tr requires edits in two places, which allows a human opportunity to make mistakes. With the latter, changing the type of p_tr in just one place will still result in the correct size being requested.
struct person p = {.name="apple"};
^This is Automatic allocation for a variable/instance of type person.
struct person* p_tr = malloc(sizeof(person));
^This is dynamic allocation for a variable/instance of type person.
Static memory allocation occurs at Compile Time.
Dynamic memory allocation means it allocates memory at runtime when the program executes that line of instruction
Judging by your comments, you are interested in when to use one or the other. Note that all types of allocation reserve a computer memory sufficient to fit the value of the variable in it. The size depends on the type of the variable. Statically allocated variables are pined to a place in the memory by the compiler. Automatically allocated variables are pinned to a place in stack by the same compiler. Dynamically allocated variables do not exist before the program starts and do not have any place in memory till they are allocated by 'malloc' or other functions.
All named variables are allocated statically or automatically. Dynamic variables are allocated by the program, but in order to be able to access them, one still needs a named variable, which is a pointer. A pointer is a variable which is big enough to keep an address of another variable. The latter could be allocated dynamically or statically or automatically.
The question is, what to do if your program does not know the number of objects it needs to use during the execution time. For example, what if you read some data from a file and create a dynamic struct, like a list or a tree in your program. You do not know exactly how many members of such a struct you would have. This is the main use for the dynamically allocated variables. You can create as many of them as needed and put all on the list. In the simplest case you only need one named variable which points to the beginning of the list to know about all of the objects on the list.
Another interesting use is when you return a complex struct from a function. If allocated automatically on the stack, it will cease to exist after returning from the function. Dynamically allocated data will be persistent till it is explicitly freed. So, using the dynamic allocation would help here.
There are other uses as well.
In your simple example there is no much difference between both cases. The second requires additional computer operations, call to the 'malloc' function to allocate the memory for your struct. Whether in the first case the memory for the struct is allocated in a static program region defined at the program start up time. Note that the pointer in the second case also allocated statically. It just keeps the address of the memory region for the struct.
Also, as a general rule, the dynamically allocated data should be eventually freed by the 'free' function. You cannot free the static data.

Does a pointer in an array of pointer to struct, if set to NULL, allocate memory?

I'm new to C and this is my first question:
for the this structure:
typedef struct Branch
{
Tree * thisTree;
struct Branch * nodes[];
} Branch;
it seems to work fine if I do the following:
Branch branch1;
branch1->nodes[0] = NULL;
even if I do not allocate memory for the pointer nr 0 in the array this way:
branch->node[0] = (Branch *) malloc(sizeof(Branch *));
if i check with this code:
if ( branch1->nodes[0] == NULL)
printf("is NULL");
it prints to the output: is NULL
So my question is:
has there been allocated memory for the pointer?
branch1->nodes[0]
because I have a lot of structures and if I initialise each branch with a fixed number of pointers I get a lot of allocated data (if I check with the sizeof function).
Is this way: setting to NULL (above) a wrong way of thinking ?
My problem is that the allocation of memory for a pointer is 4 bytes. So not having a declared number of pointers in the array, when does it allocate memory for it ?
Sorry
I tried to keep the question simple but I need to reach a string through the structure pointer in the next branch
this means that the struct I use is
typedef struct Branch
{
Tree * thisTree;
char *string;
struct Branch * nodes[];
} Branch;
So if I do not
branch->node[0] = (Branch *) malloc(sizeof(Branch *));
and than
branch->node[0]->String = strdup("text");
I ge a compiler error.
No. The null pointer does not allocate any memory to store it on the heap because there is nothing to allocate (hence the "null").
Your nodes array does allocate memory to store null pointers itself, but just as much memory it would take to store null pointers array of integers, floats, structs, you name it.
Essentially you are allocating memory to the pointer, and placing the value NULL in there, which in C is normally 0. But the value has to be placed in allocated memory, in this case allocated to the pointer, so yes, there is still allocated memory to the pointer, you just set it's value to zero.
You would however have nullified the pointer, losing access to that memory, if you had written branch->node = NULL;, but that is not the right way to remove it, as the memory is still allocated but just unreachable, instead you should use free(branch->node); to un-allocate the memory, in case you want to do that.
Concerning the number of allocated positions in memory, that would be defined by the times you multiply the sizeof() function:
int number = 2; //assume you want two elements
branch->node[0] = (Branch *) malloc(number*sizeof(Branch *));

Proper way to have two pointers point to the same memory chunk

I have a structure:
struct generic_attribute{
int current_value;
int previous_value;
};
And a constructor which outputs a pointer to this structure:
struct generic_attribute* construct_generic_attribute(int current_value){
struct generic_attribute *ga_ptr;
ga_ptr = malloc (sizeof (struct generic_attribute));
ga_ptr->current_value = current_value;
ga_ptr->previous_value = 0;
return ga_ptr;
}
Now, in another function, I want to define a pointer and set it to point to the same address as the pointer that the above constructor outputs.
struct tagged_attribute* construct_tagged_attribute(int num_args, int *args){
...
struct generic_attribute* generic = malloc (sizeof(struct generic_attribute));
generic = construct_generic_attribute(args[0]);
...
}
It looks to me that what I am doing here is this:
1) I define a pointer "generic" and allocate a memory chunk to hold an instance of generic_attribute structure.
2) I call a function construct_generic_attribute within which, the program once again allocates a memory chunk of size of a generic_attribute structure. It outputs a pointer to this memory chunk.
3) In construct_tagged_attribute I set "generic" pointer equal to the pointer output by the construct_generic_attribute function, so now both of them point to the same memory slot.
However, it appears that I am allocating twice as much memory as I need to allocate.
Is there a way for me to allocate memory only once without getting a segmentation fault for failing to allocate space for "generic" pointer? Alternatively, am I misunderstanding what is happening in this code?
struct generic_attribute* generic = construct_generic_attribute(args[0]);
Should do the trick. Pointer variable is just that, a variable. You can trade pointer values around just like numbers.
Yes, you're misunderstanding, but I can't quite figure out what you think is happening to explain how it's wrong.
struct generic_attribute *generic = construct_generic_attribute(args[0]); a pointer is a kind of value. If you assign a pointer to another, you get two pointers to the same thing, without any allocation of memory. Since C doesn't manage memory for you, it's up to you to make sure that any object that's allocated is freed exactly once, and that you don't try to use pointers to an object after it's been freed.
Here
struct generic_attribute* generic = malloc (sizeof(struct generic_attribute));
you allocate a memory block, big enough to keep a generic_attribute structure, then store a pointer to that structure (technically: an address of the block) in the generic variable. Note: you do not initialize the structure members.
Then in
generic = construct_generic_attribute(args[0]);
you call a function, which internally allocates (another) block of memory and initializes it and returns a pointer to it (which was stored in a ga_ptr variable during the function execution). The pointer returned is then assigned to the generic variable, overwriting the value stored there by a previous instruction. Consequently you loose an access to the first allocated structure.
EDIT
I'm afraid I do not quite understand what you're trying to achieve. If you want two pointers to the same structure, just declarega1 and assign it a pointer to the created structure:
struct generic_attribute *ga1 = construct_generic_attribute(args[0]);
then make a copy of the pointer:
struct generic_attribute *ga2 = ga1;

Do every variable declared as pointer have to allocate memory?

Well, I am new to C. I would like to know as my title says.
Suppose I declare pointers as following,
char *chptr1;
char **chptr2;
int *i;
int **ii;
struct somestruct *structvar1;
struct somestruct **structvar2;
Then,
Do I need to allocate memory for every variable, before storing data into them?
Is there any special case when I do not need to allocate memory for them? for this I know one for char pointer,
strdup() which allocate memory itself, we have not to care much about it.
Any further suggestions are welcome.
Pointers point at things. It's up to you what you make them point at.
You can leave them uninitialized and don't use them: int * q; That's a little silly.
You can make them point to something that exists: int x; int * q = &x;
You can store the address of dynamically allocated memory in them: int * q = malloc(29);
First thing you need to understand is, pointers are variables which are used to store addresses of memory or addresses of other variables. When you declare a pointer, you are allocating memory for that pointer and not to data pointing by that pointer.
For example,
char *ptr; //Here you allocated memory for pointer variable.
ptr = malloc(sizeof(char)); // allocated memory for the data pointed by ptr
Then call free() after using memory
free(ptr); // DE-allocates memory pointed by ptr and not variable ptr.
Do I need to allocate memory for every variable, before storing data into them?
It depends on the use case.
Let's assume you have aprogram where you can enter a user name, but if no user name is entered, a hardcoded value "Default User" is shown. Now you want to pass arround that name. If the user entered a name you might have allocted some space for it, and pass aorund that pointer. If no user name is given you are pointing to that hard coded value, which you already predefined, and you don't need to allocate memory for it.
char const *Default = "Default User"
char *username = NULL;
username = getUser(); // here the name is allocated dynamically if it is present.
if(username == NULL)
username = Default;
In the above case, the sapce for the "Default User" String is already reserved in the executable by the compiler, so you need not to allocate additional memory for it, unless you want to manipulate it.
Another case could be when you program a low level device, and you have a pointer to a hardware buffer provided by the device. In such a case you also wouldn't allocate memory, but you would still use the pointer for that buffer which may be on a fixed address. So you would use the pointer like this (Example which would change the screen border color on a C64):
char *BorderColor = 0xd020;
*BorderColor = 0;
I think that in C, a variable is a pointer added * with a memory. And a pure pointer has no memory. So if we want to store a data, we need to give the pointer a memory.
Sure, there are many ways to assign the memory.
First:
uint32_t x;
uint32_t *p = &x;
uint32_t array[10];
uint32_t *q = array;// equals to int *q = &array[0];
Second:
#define NUM_MACRO ((uint32_t) 10)
//we must free after we using. Or, perhaps we we will get a segment fault.
uint32_t *p = malloc(size(uint32_t) * NUM_MACRO);

Setting the first two bytes of a block of memory as a pointer or NULL while still accessing the rest of the block

Suppose I have a block of memory as such:
void *block = malloc(sizeof(void *) + size);
How do I set a pointer to the beginning of the block while still being able to access the rest of the reserved space? For this reason, I do not want to simply assign 'block' to another pointer or NULL.
How do I set the first two bytes of the block as NULL or have it point somewhere?
This doesn't make any sense unless you're running on a 16-bit machine.
Based on the way that you're calling malloc(), you're planning to have the first N bytes be a pointer to something else (where N may be 2, 4, or 8 depending on whether you're running on a 16-, 32-, or 64-bit architecture). Is this what you really want to do?
If it is, then you can create use a pointer-to-a-pointer approach (recognizing that you can't actually use a void* to change anything, but I don't want to confuse matters by introducing a real type):
void** ptr = block;
However, it would be far more elegant to define your block with a struct (this may contain syntax errors; I haven't run it through a compiler):
typedef struct {
void* ptr; /* replace void* with whatever your pointer type really is */
char[1] data; } MY_STRUCT;
MY_STRUCT* block = malloc(sizeof(MY_STRUCT) + additional);
block->ptr = /* something */
memset(block, 0, 2);
memset can be found in string.h
Putting the first two bytes of the allocated memory block to 0 is easy. There is many ways to do it, for example:
((char*)block)[0] = 0;
((char*)block)[1] = 0;
Now, the way the question is asked show some misunderstanding.
You can put anything in the first two bytes of your allocated block, it doesn't change anything for accessing the following bytes. The only difference is that C string manipulation operator use as a convention that strings end with a 0 byte. Then if you do things like strcpy((char*)block, target) it will stop copying immediately if the first byte is a zero. But you can still do strcpy((char*)block+2, target).
Now if you want to store a pointer a the beginning of the block (and usually it's not 2 bytes).
You can do the same thing as above but using void* instead of char.
((void**)block)[0] = your_pointer;
You access the rest of the block as you like, just get it's address and go on. You could do it for example with.
void * pointer_to_rest = &((void**)block)[1];
PS: I do not recommand such pointer games. They are very error prone. Your best move would probably be to follow the struct method proposed by #Anon.
void *block = malloc(sizeof(void *) + size); // allocate block
void *ptr = NULL; // some pointer
memcpy(block, &ptr, sizeof(void *)); // copy pointer to start of block
I have a guess at what you're trying to ask, but your wording is so confusing that I could be totally wrong. I am assuming that you want a pointer that points to the "first 2 bytes" of the block you allocated, and then another pointer that points to the rest of the block.
Pointers carry no information about the size of the memory block that they point to, so you can do this:
void *block = malloc(sizeof(void *) + size);
void *first_two_bytes = block;
void *rest_of_block = ((char*)block)+2;
Now, first_two_bytes points to the beginning of the block that you allocated, and you should just treat it as if it pointed to a memory area 2 bytes long.
And rest_of_block points to the portion of the block starting 3 bytes in, and you should treat it as if it pointed to a memory area 2 bytes smaller than what you allocated.
Note, however, that this is still only a single allocation, and you should only free the block pointer. If you free all three pointers, you will corrupt the heap, since you will be calling free more than once on the same block.
While implementing a map interface using a hash table I faced a similar issue, where each key-value pair (both of which are not statically sized, omitting the option of defining a compile-time struct) had to be stored in block of heap memory that also included a pointer to the next element in a linked list (should the blocks be chained in the event that more than one is hashed to the same index in the hash table array). Leaving space for the pointer at the beginning of the block, I found that the solution mentioned by kriss:
((void**)block)[0] = your_pointer;
where you cast the pointer to the block as an array, and then use the bracket syntax to handle pointer arithmetic and dereferencing, was the cleanest solution for copying a new value into this pointer "field" of the block.

Resources