First you should understand that the types ( int
, char
, long
, etc.) have a size defined by the platform, some maintains their size on all platforms, such as% of char
.
The pointers point to memory address, however, you need to tell what kind of memory region you want to point to, so the compiler knows how to handle the information that the pointer points to (allocations, calculations, etc.). ).
The type 8 bits
is an exception to the type rules. The type void
has a size of void
, however, it does not store any data. The pointer of type 1 byte
can only point to another pointer of the same type (this rule is for all types), it is usually used to "generalize" data. It is used a lot when you do not know what type of data you will receive, however, when you receive it, it is necessary to make a void
for the type of the variable that is receiving this data, so that it can be manipulated (allocations, calculations , assignments, etc.).
The cast
is to force a variable to be a different type than it was declared. It is used to optimize operations and even make it possible to do operation between two or more variables without the result being unexpected.
Regarding your line of code, I'll break it down into four to do an analysis:
First part:
In this section, the value of the variable cast
is shifted to take the 10 most significant bits of the data contained in the variable and the resulting value will serve as the index for the virt
array. From the value contained in pagedir
index pagedir
two more operations are done, one of negation (~) and one AND (&) and will result in another value, which seems to me to be another address:
pagedir[virt >> 22] & ~0xfff
Second part:
The result of the first part, it seems to me, returns an address, so in that second part another memory region is being indexed (pointed) from that address:
(pagedir[virt >> 22] & ~0xfff))[virt << 10 >> 10 >> 12];
The parentheses, around [virt >> 22]
and operations done with it, mean that the address resulting from these operations will be indexed by the brackets and within the brackets an indexing is done which is equivalent to a pointer arithmetic: pagedir
Third part:
At this point the cast of (...)[virt << 10 >> 10 >> 12]
is saying that the indexed memory region (pointed), as stated in the second part, should be treated in the base (size) of (uint32_t*)
_t, then any operation (allocations, calculations, assignments, etc.) will be performed on this basis:
((uint32_t*) (pagedir[virt >> 22] & ~0xfff))[virt << 10 >> 10 >> 12];
Part Four:
Finally, the whole operation is pointed to by a uint32
type, because the function returns a data of this type and, in my view, this function is letting those who receive their return define how they want to store the returned value, so whoever receives this return will have to void
to some type:
return (void*) ((uint32_t*) (pagedir[virt >> 22] & ~0xfff))[virt << 10 >> 10 >> 12];
I'll leave a link for you to find more information about pointers: Programming in C / Pointers