Arrow vs. Dot in C Structs? - c

I've got a specific question regarding the arrow vs. dot notation for structs in C. I understand that -> is used for struct pointers, and . is used for objects, however I've been having some trouble parsing some code I found online.
typedef struct node{
int data;
}Node;
typedef struct heap{
int size;
Node *dataArray;
}Heap;
typedef struct plan{
int maxPile;
Heap *heapArray;
}Plan;
Given this code, if I create:
Plan *p
And then I want to access a specific index in the heapArray inside Plan I would do:
p->heapArray[i]
From here, though if I want to access either the size of the dataArray inside a struct heap, would I use '->' or '.'?
So if I wanted to get the first element of the data array of that heap would I do:
p->heapArray[i].dataArray[0]
or
p->heapArray[i]->dataArray[0]

The correct answer is
p->heapArray[i].dataArray[0]
because when you use the subscript on the heapArray pointer, it's like doing pointer arithmetic and then dereferencing the pointer, something like this
(*(p->heapArray + 1)).dataArray[0]
so when you dereference it, the type of it becomes Heap which means it's not a pointer and has to be accessed with a . and not a ->.

p->heapArray[i] is of type Heap, which is a struct, so you'd use ..

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.

Using "." vs "->" in pointers and structures

I am confused as to when to use . vs. ->.
I have seen both being used when referencing an item in a structure.
Here's an example:
typedef struct stack{
int top;
double numbers[100];
}stack;
stack the_stack;
the_stack.top = 0;
Would you use -> if this was the following was the case:
typedef struct stack{
int top;
double numbers[100];
} *stack;
stack the_stack;
the_stack->top = 0;
If not, when is . used in C?
The . operator is the value membership operator. This means that it is used when you are accessing the object's value.
The -> operator is the pointer membership operator. The object before it is a pointer to a structure, and this goes into the pointer to access the object's members.
To use your example:
typedef struct stack {
int top;
double numbers[100];
} stack;
Then you could do any of these:
struct stack my_stack, *my_stack_pointer;
my_stack.top = 3; // Change the value of stack.top
// From whatever my_stack_pointer points to, take the value of top, and
// assign 3 to it
(*my_stack_pointer).top = 3;
// Same idea as the previous, only abbreviated
my_stack_pointer->numbers[0] = 3
Your examples are both correct. . is used for a structure element while -> is used for dereferencing a pointer to a structure.
In genera, x->y is the same as (*x).y. (The latter construct is generally discouraged.
It's simple, really. a->b is the same as (*a).b, that is, first dereference the pointer a, then access member b.
In C++, it is in theory possible to do different things with the two operators, but it's bad practice to do so (since it contrasts with everything people expect from the rest of C or C++).
the_stack->top is only shorthand for (*the_stack).top.
whenever you have a pointer to a structure, you must dereference the pointer then access the elements in the structure, the arrow is a shortcut for doing (*the_stack).top replace this with the arrow now its much cleaner and nicer the_stack->top
When u use pointer to a structure , '->' is used '.' otherwise.
typedef struct stack{
int top;
double numbers[100];
} *stack;
stack the_stack;
the_stack->top = 0; // equivalent to (*the_stack).top=0
We use . for object.attribute.
And -> is just syntactic sugar for, (*a).attribute = a->atribute
This -> is used mainly so the programmer by fault doesn't writes *a.attribute.
. operator is used to when you have an object to the structure.
-> is used when you have a pointer to the structure, you de-reference it and access the memory location.
But keep in mind you need to allocate the memory first to de-reference your pointer, in case of object, you don't need to.

C - passing elements from within structures to functions

I have a structure comprised of an array of pointers to other structures of a different type.
typedef struct{
NodeT* nodes[2];
int size;
}stackT;
with:
typedef struct{
char info;
}NodeT;
And I have a pointer to the above (first) structure:
stackT* stackPtr;
Assuming the memory is allocated for the stackT structure as well as both NodeT structures with associated assignments for the members of both NodeT structures, how would I pass to a function one of the pointers in stackT?
For example:
void setChar(NodeT* nodePtr, char setTo){
nodePtr->info = setTo;
}
called with line:
setChar(stackPtr->nodes[0], 'A');
Does not work. I figured it had something to do with the -> syntax dereferencing the pointer whereby I am actually passing in a structure. I do not get any compilation errors, but when I check for the assignment by printing whatever is stored in char info I do not get anything.
Is the notation incorrect or do I have issues elsewhere in the program perhaps? I just wanted to rule this out first (proper passing syntax).
If someone is looking for a solution to this problem, the above code was actually correct.
Assuming you have an array of pointer in some structure and you wish to pass such a pointer, the correct syntax would be:
someFunc( structPtr->ptrArray[0] )
The line:
structPtr->ptrArray[0]
Actually returns a pointer, and not whatever the pointer is pointer to.
(*structPtr).ptrArray[0]
Is also equivalent.
That being said, I either mistakenly interpreted the information before me, or I had underlying errors elsewhere in the my code.

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.

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