How can lParam be casted into more than one structures? - pointers

I saw this piece of code below in here. I tested it and it works all right.
// g_hLink is the handle of the SysLink control.
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code) // CAST TO NMHDR*
{
case NM_CLICK: // Fall through to the next case.
case NM_RETURN:
{
PNMLINK pNMLink = (PNMLINK)lParam; // CAST TO NMLINK*
LITEM item = pNMLink->item;
if ((((LPNMHDR)lParam)->hwndFrom == g_hLink) && (item.iLink == 0))
{
ShellExecute(NULL, L"open", item.szUrl, NULL, NULL, SW_SHOW);
}
else if (wcscmp(item.szID, L"idInfo") == 0)
{
MessageBox(hDlg, L"This isn't much help.", L"Example", MB_OK);
}
break;
}
}
break;
The parameter lParam is casted to both NMHDR* and NMLINK* types. The documentation of WM_NOTIFY message says that lParam can be casted to NMHDR*, but NMLINK is a different structure which encapsulates NMHDR.
What does actually happen when we cast lParam to an arbitrarily chosen structure between these two?

NMLINK contains NMHDR as its first element:
struct NMLINK {
NMHDR hdr;
LITEM item;
};
And so pointer to NMLINK equals to the pointer to its first member (which is NMHDR structure sitting at offset 0), they are the same. It means that you can cast NMHDR* to NMLINK*.

Related

Comparing two different pointers to elements of a linked list

Anyone knows if there are there any method for comparing the two pointers, let's say there are two pointers ptr1 and ptr2, as shown in the picture, how can i perform some operations similar (ptr2 < ptr1) to check whether a specific pointer passed another pointer, for example to check whether ptr2 passed ptr1 such that ptr2 is on the right side while ptr1 is on the left side. Thank you in advance.
Comparing the pointer values themselves will not tell you which node is before the other one in a linked list. For that you will need to step through your linked list.
You could have these pointers traverse the linked list in tandem. The one that reaches the end of the list first is necessarily the one that is coming after the other one.
In pseudo code (c-style):
int compare(node* ptr1, node* ptr2) {
if (ptr1 == ptr2) return 0; // equal
while (ptr1 != NULL && ptr2 != NULL) {
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}
return ptr2 == NULL ? -1 : 1;
}
If the list is long, and the pointers are not far from each other, you can gain some time by also checking whether one of the traversing pointers becomes equal to an original pointer. Then you can also take your conclusions:
int compare(node* ptr1, node* ptr2) {
if (ptr1 == ptr2) return 0; // equal
cur1 = ptr1;
cur2 = ptr2;
while (true) {
if (cur2 == NULL || cur1 == ptr2) return -1; // ptr1 before ptr2
if (cur1 == NULL || cur2 == ptr1) return 1; // ptr2 before ptr1
cur1 = cur1->next;
cur2 = cur2->next;
}
}
All this assumes that the given pointers are both pointing to members of the same linked list. With the above function you can now do:
// ...
int res = compare(ptr1, ptr2);
if (res < 0) output("*ptr1 comes before *ptr2");
if (res > 0) output("*ptr1 comes after *ptr2");
if (res == 0) output("*ptr1 is the same as *ptr2");

Segmentation fault when assigning integer to pointer

I'm trying to assign my node value to a pointer, but gdb gives me segmentation fault when the code is ran. What can I do?
void biggerPotion(No* node, int bottleSize, int *aux){
if(node == NULL)
return;
maiorPocao(node>left, bottleSize, aux);
maiorPocao(node->right, bottleSize, aux);
if((node->value >= garra) && (node-> value < *aux))
*aux = node->value; //here is the issue
}
Other relevant parts of the code are:
for(i=0; i< nBottles;i++){
a = 1000; //i declared that
biggerPotion(potions,bottleSize[i],&a);
}
Okay, since the errant line is:
*aux = node->value;
then either aux is the problem or node is (because they're the only two pointers being dereferenced on that line).
I would print them both out before executing that if block just to be certain:
fprintf(stderr, "node is %p, aux is %p\n", node, aux);
Given the large use of node and small use of aux, it's probably the latter that's causing the issue, in which case you should examine what you're passing to the top-level call of biggerPortion. You should post that top-level call, including the declaration of whatever variable you're passing in.
In any case, you can test that by simply changing:
*aux = node->value;
into:
{
int temp = node->value;
}
If the problem disappears then it's definitely the aux pointer being wrong somehow. Make sure you are actually passing in a pointer, such as with:
int myVar;
biggerPotion(rootNodePtr, 42, &myVar);

map interface pointer method receiver

I have a the following code
http://play.golang.org/p/d-bZxL72az
package main
import "fmt"
type Variables struct {
sum uint64
highest uint64
}
type Data struct {
count uint64
mValue map[string]Variables
}
func (v Variables) Add(value Variables) Variables {
v.sum += value.sum
if v.highest == 0 {
v.highest = value.highest
} else if v.highest < value.highest {
v.highest = value.highest
}
return v
}
func (v *Variables) AddPointer(value Variables) {
v.sum += value.sum
if v.highest == 0 {
v.highest = value.highest
} else if v.highest < value.highest {
v.highest = value.highest
}
}
func main() {
var instances [2]Variables
instances[0] = Variables{sum: 5, highest: 3}
instances[1] = Variables{sum: 10, highest: 2}
var d Data
d.mValue = make(map[string]Variables)
for i:= 0; i < len(instances); i++ {
d.mValue["one"] = d.mValue["one"].Add(instances[i])
d.mValue["two"].AddPointer(instances[i])
}
fmt.Println(d.mValue["one"])
fmt.Println(d.mValue["two"])
}
I get the error
# command-line-arguments
/tmp/sandbox209565070/main.go:42: cannot call pointer method on d.mValue["two"]
/tmp/sandbox209565070/main.go:42: cannot take the address of d.mValue["two"]
(I think) I understand the second error cannot take address - because, it is a map, it cannot take the address (is that correct?)
Is it the same reason for the first error as well (cannot call pointer method)?
Is there a way to use pointer methods on structures that are within the maps..
Yes, same reason. In order to call a method with a pointer receiver, you either need to have a pointer in the first place, or you need an addressable value and Go will automatically take the pointer for you.
What you can do, then, is to make mValue a map[string]*Variables instead of a map[string]Variables. Then you will be storing a pointer to an already-allocated, guaranteed-addressable Variables in the map, and you'll be able to call methods on that pointer.
To expand on the previous answer…
In practice, this isn't usually a problem. If the type makes more sense without pointers (e.g. a small struct where value semantics make more sense) then you wouldn't have pointer receivers and the issue wouldn't arise.
If pointer receivers make sense then you should probably be using pointers to the type in most places, such as in maps (as hobbs said) and you wouldn't have methods that took non-pointer arguments or returned non-pointer values (non-pointer receivers could still make sense and would be easy to use). Again, the issue wouldn't arise.
In the first case if you wanted to use a pointer receiver with a non-pointer map entry, you could use a temporary (addressable) variable and reassign it back into the map.
x := d.mValue["two"]
x.AddPointer(instances[i])
// AddPointer uses a pointer receiver; `x` needs to be addressable,
// it will contain a copy of the value from the map and that copy may
// be changed by the method so we need to copy the new version back
// into the map.
d.mValue["two"] = x
In the second case a few issues arise. First, to avoid nil pointers you need to either initialize the map entries or check for nil/existance on map reads (or make make your pointer receiver methods handle nil valued receivers, but that doesn't help for non-pointer receiver methods though). Second, if for some silly reason you have pointers but still have a method that returned a non-pointer you'd have to use a different syntax to assign to the map.
Something like this perhaps:
// Initialize some map entries to avoid nil pointers
d.mValue = map[string]*Variables{
"one": &Variables{},
"two": &Variables{},
}
for i := 0; i < len(instances); i++ {
// Just calling the non-pointer reciever is easy/fine:
d.mValue["one"].Add(instances[i])
// But you can't do this:
//d.mValue["one"] = d.mValue["one"].Add(instances[i])
// cannot use d.mValue["one"].Add(instances[i]) (type Variables) as type *Variables in assignment
*d.mValue["one"] = d.mValue["one"].Add(instances[i])
d.mValue["two"].AddPointer(instances[i])
}

pointer as a parameter

I have a problem with this function I created, the function should return the number of characters entered in the array. but always return 20 that its the limit of the array itself.
Code:
int LongitudCadena (char *pcadena) {
// cantidad its the counter of chars that in the array
int cantidad=0;
//M its a constant equals 20, that its the limit of the array
for(int a=0;a<M;a++){
if(pcadena!=0){
pcadena++;
cantidad++;
} else {
return 0;
}
}
return cantidad;
}
Replace if(pcadena!=0) by if(*pcadena!='\0').
Also, change the else condition to either
else
{
return cantidad;
}
or
else
{
break;
}
pcadena, the pointer, is never going to be 0 (NULL)... what you meant that the character it points to is '\0'
if (*pcadena)
Another problem is once you find the terminator, you return 0. You should return cantidad there.
Note: cantidad == a
There are several problems with the code. First of all, you should test the content of the address the pointer points at.
...
if(*pacadena!=0) {
....
Secondly, why do you return 0 in the while loop when pcadena is 0? Shouldn't you return the current length? Assuming your data always terminate with \0, then your for loop should look something like this:
for(int a=0;a<M;a++){
if(*pcadena){
pcadena++;
cantidad++;
} else {
return cantidad;
}
}
Further, if your data is indeed terminated by \0, then you should just use the strlen function instead. There's no need to rewrite this.

implicit conversion of 'bool' (aka 'signed char') to 'nsdata *' is disallowed with arc

When perform a migration of my project to Obejctive-C ARC, i got one error:
implicit conversion of 'bool' (aka 'signed char') to 'nsdata *' is disallowed with arc
The function Xcode is referring to for this error is returning NO or nil although its returning type is of type NSData:
- (NSData *)compressBytes:(Bytef *)bytes length:(NSUInteger)length error:(NSError **)err shouldFinish:(BOOL)shouldFinish
{
if (length == 0) return nil;
int status;
if (status == myVariable) {
break;
} else if (status != y_OK) {
if (err) {
*err = [[self class] deflateErrorWithCode:status];
}
return NO;
}
However, i am not quite sure i know how to fix that, any idea will be appreciated.
Under ARC you are only allowed to return an object or nil. Period.
This is because ARC not just requires, but DEMANDS that you don't do anything fishy with pointers - that pointers either point to objects or nil.
ARC is having fits because you are trying to stuff NO (a zero value) into a pointer. This violates the rules and that is why you are getting an error.
We can't help you fix it because a) we don't know what the valid return values are for (why NO? Why not nil?). Since this appears to be a code fragment, it is hard to help you. Sorry.
Just don't do that. NO is not in any sense a valid return value for that function. Your code was broken before ARC, and now it's still broken after.
Also, these lines:
int status;
if (status == myVariable) {
break;
}
are exactly the same as these:
if (myVariable == nil) {
break;
}
except written in a really confusing way, and relying on ARC to initialize status. I'm pretty sure that's not what you wanted.
Basically, this method looks completely wrong.

Resources