Pointer to struct containing structs - c

I am writing a multithreaded application and would like to pass around pointers to a struct.
Do the structs in the struct need to be malloced or if the outer struct is malloced will it prevent the internal structs from being deleted or lost when passing around the pointer?
Struct I am asking about is
struct thread_data
{
position starttile;
position destinationtile;
char *message;
};
where position is a struct itself that contains no pointers

If the struct contains child structs, then it is generally all one block of memory. And so there would be no separate allocation.
If the struct instead contains pointers to structs, then my previous comment would not apply. In this case, it kind of depends on what you are doing.
Had you considered posting a tiny bit of code so people would have a clue what you had in mind.

You will probably find it easier to manage memory if you do
struct X {
struct Y data;
};
struct X* var = malloc(sizeof(struct X));
instead of
struct X {
struct Y* pData;
};
struct X* var = malloc(sizeof(struct X));
var->pData = malloc(sizeof(struct Y));

If your outer struct contains actual structures, there's no need to allocate them separately.
If your outer struct contains pointers to structures, then they'll need to be allocated somewhere.
It is easier if your outer structure contains actual structures. Even so, with pointers, simply make sure that you never make the pointer to the outer structure available to other threads until the inner structures are fully allocated - which avoids threading issues on allocation. Deallocation will require suitable care to ensure exclusive access.

Related

Is there a principle for choosing between embedding a struct itself or the pointer to a struct inside a struct?

This is a code snippet from qemu.(qemu-5.1.0 include/hw/arm/smmu-common.h)
typedef struct SMMUDevice {
void *smmu;
PCIBus *bus;
int devfn;
IOMMUMemoryRegion iommu;
AddressSpace as;
uint32_t cfg_cache_hits;
uint32_t cfg_cache_misses;
QLIST_ENTRY(SMMUDevice) next;
} SMMUDevice;
I've seen many such codes until now but I am now curious if there is any principle/rule in choosing between
embedding a struct A inside a struct B
embedding a pointer to the struct A inside a struct B
Two things that come to my mind right away is that if a struct A is to be shared by many structs, it is better to use pointer. or if the struct containing the struct(that is, struct B) is to be frequently passed as a function argument, it would be better to use pointer(pointer to struct B as argument, or pointer to A inside struct B and struct B is the argument) because copying the struct to stack would take long time.
I am curious if there are other important rules.
There's no correct answer because it depends on what you want to use them for. Storing a struct inside another struct is generally more efficient, since it gives faster access and better data cache use.
However, it isn't as flexible. If you wish to swap out the whole contents of a big struct for something else, it goes much faster to just swap two pointers than doing a hard copy of all the data. Pointers also enable different forms of allocation - you could have a static storage struct with a pointer at dynamically allocated memory for example.
if a struct A is to be shared by many structs, it is better to use pointer
I don't see how that matters at all. It's just a . vs -> notation by the code using it.
or if the struct containing the struct(that is, struct B) is to be frequently passed as a function argument, it would be better to use pointer
No that's nonsense, you'd always pass the outer struct through a pointer no matter what members it got. Passing it by value doesn't make any sense in either scenario.

Allocation of variables inside dynamically allocated structs

Suppose to have a struct that contains a pointer to an array and its size, like this one:
typedef struct {
int * array;
int arr_size;
}IntArray;
and want to have this inside another struct, it can be done in two ways:
typedef struct{
IntArray ia;
//other variables
}Base1;
typedef struct{
IntArray * ia;
//other variables
}Base2;
What happens when I dynamically allocate Base1 and Base2 (e.g Base1 b1 = (Base1 *)malloc(sizeof(Base1));) and why should I choose one way instead of the other?
Nested structs' space exist as space in their parent struct, which means they don't need their own allocation (but they might still need their own initialization), whereas struct fields that are pointers need to be both allocated and freed when the parent object is initiated (this is a common cause of memory leaks in C because it does not have automatic object destructors like C++ does). Though if using a pointer you could point to another array/object that might exist on the stack (thus avoiding malloc/free) but then you might run into object lifetime bugs depending on the difference on scope and lifetimes of your objects.
Nested structs exist in-place, so they cannot be shared by other instances. This may or may not be ideal (you could solve this with a template in C++, in C you'd have to settle for a hideous preprocessor macro).
Because dynamically-allocated objects (such as your array and your Base2 type's nested ia member) exist in different locations in physical memory it means your code will not take advantage of spatial locality that the CPU's caches can take advantage of and you'll incur a double pointer dereference. So your code will run slower.
Anyway: when in C, you should generally try to minimize pointer use.
Basically the question is the same as, should I allocate a struct or a pointer to a struct? That is:
IntArray myStruct;
or
IntArray *myStructPtr;
The fact that the variables in question are within a struct makes no difference, you can choose either.
And you access them in the same manner as you would if they were not inside another structure, after referencing the field inside the outside structure of course, so
Base1 contains the actual IntArray struct so you would
Base1 *b1 = malloc(sizeof(*b1));
b1->ia.array = malloc(yourSizeHere);
Base2 contains a pointer to a IntArray struct, so you would need to point it to an existing IntArray struct or malloc() memory for it, and then access it as a pointer.
Base2 *b2 = malloc(sizeof(*b2));
b2->ia = malloc(sizeof(*(b2->ia)));
b2->ia->array = malloc(yourSizeHere);

How is it possible for a C struct to reference itself?

How does a C compiler (I'm using GCC) know what to do with the following?
struct node
{
int x;
struct node* next;
};
More precisely, if node has yet to be completely defined yet (we have not reached the closing curly brace), then how does the compiler know how big a struct ought to be?
While I realize that "pointing to" only requires an address, incrementing pointers does require the size of the data it points to.
The size of the struct is not important, as a pointer to the struct is being stored, not the struct itself.
In terms of incrementing pointers to struct; that is done outside of the struct definition, so again, is not important.

pointer to structure and self pointers

What is the difference between self referential pointer in structure and pointer to structure?
struct abc
{
int data;
struct abc *next;
}
struct abc *pt;
What are the differences between *next and *pt??
How they differ in their use??
I am really in doubt between these two
I am a beginner
First example is used mainly for linked list
Are pointer to structure node and self referential pointer the same thing?
please see
see-programming.blogspot.in/2013/05/chain-hashing-separate-chaining-with.html here we have used struct hash *hashTable as an array ..how?? and can we do same with *pt
They are of the same type. They behave in the exact same way.
Some example usage:
// declare 2 structs
struct abc s1;
struct abc s2;
// point pt to s1
pt = &s1;
// point s1.next to s2
s1.next = &s2;
// access pt->data
int a = pt->data;
// access s1.next->data
int a = s1.next->data;
Differences in usage:
There's only one pt variable.
For every struct abc variable, there is a next variable.
In the context of a linked-list, there is only one head pointer, thus pt would be it.
But each node points to the next node, thus next should be used for this.
Using pointers as arrays?
Yes, this can be done with either pt or next.
A pointer just points to an address in memory. There can be any number of structs following on each other at that location.
If you want to use it as an array (or just using pointers in general), you just have to make sure you don't try to access elements that you didn't allocate memory for (with malloc for example) and free the memory after usage (if you used malloc).
Some example usage with array:
// declare a struct
struct abc s1;
// make an array of size 10
struct abc *a1 = malloc(10*sizeof(struct abc));
// give the 4th element a new value
a1[4] = s1;
// free the memory
free(a1);
I hope that helps a bit.
Conceptually, very little difference at all.
next is a member of the same structure it is pointing to. pt is not a member of the structure it is pointing to.
They are used in a similar way, except that to use next you have a have an existing struct abc, and pt can be used directly. Please consider:
myABC.next= &myOtherABC ;
pt= &myOtherABC ;
are pointer to structure node and self referential pointer same thing
They are and they are not. Depends on point of view. They are because they both point to a structure. They are not because a pointer to structure can point to any structure, and as a variable it can be a parameter, a local variable, a member of another struct, etc. But a self referential pointer is necessarily a member of a struct and points to the same struct it is a member of.
The only difference applies to people that write compilers. That is because a self-referential pointer refers to itself before itself is fully declared. So someone writing a compiler has to deal with this special case.
As a programmer (that means you), there is no difference, and the terms do not offer any additional meaning.
they are the same type but they do not contain the same value
from pt you can access next because pt point to a structure that contain next. but from next you can't access pt.
for linked list, you have to understand, that the list contain at the begining 1 element, and this element know how reach the next element of the list, it is the goal of the next pointer
There is no difference between those two pointers.
A possible difference in usage depends on the context but still does not apply to their nature of being both pointer to the same type of structure and therefore undergoing the same rules in terms of assignment, reading and arithmetics.

C - transferring information to a struct (specifically an array of strings)

This seems to be a very simple problem but I can't quite figure out which part is causing it. Basically, I have a struct that just contains an array of strings
struct command_stream{
char **tokens;
};
typedef struct command_stream *command_stream_t;
command_stream_t test;
Then later on, I parse some strings into shorter ones and end up with another array of strings
char **words = *array of strings*
words contains the correct information I want, I looped through and printed out each element to make sure I wasn't getting a faulty string. So now I just point tokens to words
test->tokens = words;
But it gives me a segmentation fault. I'm not sure why though. They're both pointers, so unless I'm missing something obvious...
EDIT: The function as a whole has to return a pointer, which is why it was set up like this, which I keep forgetting. But I think I've got it, if I just create a new typedef
typedef struct command_stream command_stream_s;
command_stream_s new_command_stream;
and just return
&new_command_stream;
That should work right? Even though new_command_stream itself isn't a pointer.
From your code excerpt, it seems that you have not declared the struct. You have successfully declared a pointer to the struct command_stream_t test; but this pointer does not point to anywhere yet.
You need to allocate memory for your struct in some way and make test reference it. For instance:
command_stream_t test =
(command_stream_t) malloc(sizeof(struct command_stream));
This way you can successfully use:
test->tokens = words;
as you intended.
Note that you don't need to use malloc to allocate the memory. The pointer can reference a local/global variable as long as it has memory associated to it (N.B. if you use a local var don't use the pointer outside the declaration scope of that var).
typedef struct command_stream *command_stream_t;
command_stream_t test;
This makes "test" a pointer. There is no memory allocated for the structure.
You need to allocate memory for the structure and make the test pointer point to the block of memory before you can dereference by saying -
test->tokens = words;
Do this:
typedef struct command_stream command_stream_t;
command_stream_t test;
test.tokens = words;
The difference is that, command_stream_t is no more a pointer type, it is the actual structure.

Resources