Consider the if statement:
if (((DbSignal*) ev->newVal.buff)->sig)
Where DbSignal is a structure.
Why is DbSignal within brackets and what is the asterisk operator doing in this case?
It is the cast: ev->newVal.buff is casted to pointer to DbSignal. Then this pointer is being dereferenced (sig member accessed)
What is the type cast: What exactly is a type cast in C/C++?
The syntax (DbSignal*) is a typecast. It converts one type to another.
In this case, the operand of the cast is ev->newVal.buff which presumably is a pointer to a character buffer. This pointer is converted to a pointer to DbSignal via the cast. The result is then dereferenced and the sig member is accessed.
We have ev which is a pointer in this case.
it points to a struct containing the variable newVal which contains a buff pointer.
So we have ev->newVal.buff
Here buff is either a char* or void* (a series of bytes, but apparently has some layout). Meaning that the memory it points to could potentially be interpreted in different ways.
By your example, we know that buff has a certain layout, corresponding to the DbSignal struct.
So in order to access ->sig we have to cast this .buff to DbSignal, basically telling that we want to interpret that memory region with the layout described by DbSignal.
Hope this gives some context.
Related
I encountered a problem in reading a piece of C code. code show as below :
#define size_of_attribute(Struct, Attribute) sizeof(((Struct*)0)->Attribute)
The function of this macro function is gets the length of the attribute in the struct. I know what this function is for, but i can't understand the meaning of "((Struct*)0)".
I will appeaciate If you can give me some explanation :).
The constant value 0 qualifies as a null pointer constant. The expression (Struct*)0 is therefore casting that null pointer constant to a pointer of type Struct *. The expression then gets the Attribute member.
Attempting to evaluate ((Struct*)0)->Attribute would result in a null pointer defererence, however this expression is the argument to the sizeof operator. This means the expression is not actually evaluated but simply examined to determine its type.
So sizeof(((Struct*)0)->Attribute) gives you the size of the Attribute member of the struct named Struct without having to have an object of that type.
This is basically accessing a member variable type without actually mentioning / creating any variable of that structure type.
Here,
the 0 is casted to the structure type pointer, and
then that pointer is used to access the member variable
which is used as the operand of sizeof operator.
Since sizeof is a compile time operation, the NULL dereference never actually executes at runtime.
It's casting a null pointer to the Struct* type so it can determine the size of the attribute of that struct. Normally, reading an attribute from NULL is illegal, but for sizeof, it doesn't actually read anything, it just looks at the definition of the struct to determine the statically defined size of the attribute of any such struct.
At least for C++, this is useful because unlike a non-pointer-based:
sizeof(Struct{}.Attribute)
it doesn't require Struct to have a default constructor. A pointer can be made with no knowledge of how to construct the object, while an actual object (even if none is actually constructed) must still be constructed in a valid way, and you can't say with any reliability how an arbitrary struct can be legally constructed.
In particular I'd like to know what ->val does in the
sizeof(((stoken_t*)(0))->val)
and what stoken_t*(0) pointer do, in particular what the (0) means?
I hope I have formulated my question clearly enough.
This is a way of accessing a member of a structure at compile time, without needing to have a variable defined of that structure type.
The cast (stoken_t*) to a value of 0 emulates a pointer of that structure type, allowing you to make use of the -> operator on that, just like you would use it on a pointer variable of that type.
To add, as sizeof is a compile time operator, the expression is not evaluated at run-time, so unlike other cases, here there is no null-pointer dereference happening.
It is analogous to something like
stoken_t * ptr;
sizeof(ptr->val);
In detail:
(stoken_t*)(0) simply casts 0 (this could be an arbitrary numeric literal) to a pointer to stoken_t, ((stoken_t*)(0)->val) is then the type of the val member of stoken_t and sizeof returns the number of bytes this type occupies in memory. In short, this expression finds the size of a struct member at compile time without the need for an instance of that struct type.
So for a while I was confused about array names and pointers.
We declare int a[10];
And somewhere down the road also have a and &a.
So I get how the syntax works. a is the array name. When it is not used as an operand for sizeof &, etc., it will be converted or "decayed" so it returns a pointer to integer holding the address of the first element of the array.
If the array name is used as an operand for sizeof or &, its type is int (*)[10]. So I guess the type is different because that "decay" does not happen.
But I still do not understand how &a works. My understanding is that it is giving me the address of whatever it was before the "decay" happened.. So before the "decay" to pointer happened, then what is it and how does the compiler work with the "original" to evaluate &a?
In comparison, if we declare int *p;
and later have &p and p somewhere in the code...
In this case the pointer to integer p is given a separate pointer cell with its address and the value at that address will be whatever address we assign to it (or the garbage value at that address pre-assignment).
a does not get assigned a separate pointer cell in memory when it is declared int a[10]. I heard it is identified with an offset on the register %ebp. Then what is happening with the compiler when it evaluates &a? The "decay" to a pointer to integer is not happening, there was no separate "pointer" in the first place. Then what does the compiler identify a as and what does it do when it sees that unary & operator is using the array name as an operand?
Given:
int a[10];
the object a is of type int[10]. The expression a, in most but not all contexts, "decays" to a pointer expression; the expression yields a value of type int*, equivalent to &a[0].
But I still do not understand how &a works. My understanding is that it is giving me the address of whatever it was before the "decay" happened.. So before the "decay" to pointer happened, then what is it and how does the compiler work with the "original" to evaluate &a?
That's not quite correct. In &a, the decay doesn't happen at all. a is of type "array of 10 int" (int[10]), so &a is of type "pointer to array of 10 int" (int(*)[10]).
There's nothing special about this. For any name foo of type some_type, the expression &foo is of type "pointer to some_type". (What's confusing about it is that this is one of the rare cases where an array name doesn't behave strangely.)
It's best to think of the words "array" and "pointer" as adjectives rather than nouns. Thus we can have an array object, an array expression, an array type, and so forth -- but just "an array" is ambiguous.
This:
int a[10];
defines an array object named a (and allocates 4 * sizeof (int) bytes to hold it). No pointer object is created. You can create a pointer value by taking the address of the object, or of any element of it. This is no different than objects of any other type. Defining an object of type some_type doesn't create an object of type some_type*, but you can create a value of type some_type* by computing the address of the object.
Then what does the compiler identify a as and what does it do when it
sees that unary & operator is using the array name as an operand?
The compiler identifies a as a 10-element integer array, and when it sees the & operator, it returns the address of that array.
Just like it would see int i = 3; as an integer, and &i as the address of that integer.
Concerning taking the address of an array: an array is an object in and of itself, so it has both a size and an address (though taking its address is seldom useful).
The conversion of an array to a pointer to its first element is a form of type coercion. It only happens if the alternative would be a compile error.
For instance, you can't compare an array to a pointer, so the array (implicitly) is coerced (cast) to an int* (to its first element) and then the pointer types are compared. In C you can compare any pointer types. C just doesn't care (though it will likely emit a warning).
This is actually comparing int* to int(*)[10] as far as types are concerned, as you said. These will necessary have the same address (regardless of typing) because arrays hold their data directly. So the address of an array will always be the address of its first element.
However, it's not an error to get the size of an array, so sizeof(a) gets the size of the entire array, as no coercion is needed to make this legal. So this is the same as sizeof(int[10]).
Your other case sizeof(&a) is really sizeof(int(*)[10]) as you said.
I have a question regarding the void pointer in c language. I would like to know Can we dereference a void pointer without knowing its type?
No, because you don't know how to interpret the data contained by the corresponding memory space. Memory itself has no type, and it is pointers that contains the type information. For example, memory pointed to by int * is interpreted as an int.
When dereferencing a void *, there is no way for the compiler to tell which type bytes starting from that address should be interpreted as. It can be a double, an unsigned long, or even an array of chars.
However, it is possible to get dereference a void * through casting, because the cast operator contains the information about object type.
No, A void pointer can be dereferenced only after explicit casting. For example:
int a = 5;
void *b = &a;
printf(ā%d\nā, *((int*)b));
TL;DR No, you can't.
While dereferencing a pointer-to-type, you generate an "object" of the type.
Since a void is not a complete type, you cannot dereference a void* directly. That is why, you need to either
copy the pointer to another pointer of a complete type
cast the pointer to another complete type
and then, you can dereference to get the object of the new complete type.
You cannot. Dereferencing a void pointer requires an explicit cast beforehand.
You can ofcourse cast it to any particular type and then dereference it without knowing its original type, but why you would want to do that is beyond me.
#define PORTC *(unsigned char volatile *)(0x1003)
#define DDRC *(unsigned char volatile *)(0x1007)
So I've been trying to read some stuff about embedded C. Initially I thought this macro was a pointer-to-pointer type but then I soon assumed the last star is actually a dereference rather than a type-cast, am I correct? Dereferencing to the location 0x1003/0x1007.
It is used like: PORTC = <some hex value>
Question is what makes this different from a pointer type-cast? Is there some sort of 'provision' in the C specifications? Or am I just an idiot...
Also I don't quite know how to phrase this and so I couldn't do a quick search first...
It's just the way the C grammar is defined.
To be a cast, the expression needs parenthesis: (type)sub-expression casts sub-expression to type type.
Your example, *(unsigned char volatile *)(0x1003) is composed of 2 sub-expressions:
a "lonely" star: *
a cast: (unsigned char volatile *)(0x1003)
The cast is composed of the type inside () and a value.
So, the whole expression is interpreted as a pointer, then de-referenced to set the memory area pointed to.
No, it is quite a cast.
First, the memory location (as integer) is cast into an appropriate pointer which is then dereferenced.
That code is basically equivalent to: Put <some hex value> in the memory at the address (0x1003) (or whatever the value is). In some embedded devices (and not only) ports are mapped at memory locations.
The cast instructs the compiler that the memory addresses 0x1003 and 0x1007 are to be treated as unsigned char volatile * pointers, and the * dereferencing operator acts on that pointer to fetch the pointed-to value, which in this case is 1 byte.
Applying the unary * makes this expression a valid lvalue (it wouldn't be so without it) which means that it is something you can assign to.