Page 1 of 1
Posted: Tue Feb 07, 2017 7:23 pm
I was wondering if line 138 of Appcache.c is correct:
if (Reason) *Reason = 0;
Can someone explain this to me? I notice there is only one equal sign. Generally, from what little I know, that means to assign, while two are used to make a comparison. So wouldn't this always fail? But I don't understand the asterisk here. Does that mean to multiply, or does it mean something else like wanting a descriptor address or specifying a type?
Posted: Tue Feb 07, 2017 7:47 pm
Here is the context for the readers:
https://svn.reactos.org/svn/reactos/tru ... arkup#l129
"Reason" is a pointer to a ULONG value (check how the "PULONG" type is defined in the headers: typedef unsigned long ULONG, *PULONG;).
Here, the code checks whether the "Reason" pointer is not
the NULL pointer. If it is not NULL, then it sets the contents pointed by the "Reason" pointer to 0 (but if the pointer is NULL, nothing is done).
Basic reminders of C programming:
Let 'var' be some variable, for example of type ULONG:
we can define a "pointer" to 'var', aka. another variable that contains the memory address of 'var', and let's call it for ease of understanding, "Reason":
Code: Select all
* Here, the asterisk means that the type of the variable pointed by 'Reason' will be a ULONG, but 'Reason' itself is a pointer to 'var'.
* The ampersand in "&var" provides you with the memory address of 'var'.
ULONG *Reason = &var;
/* Because of the above-mentioned typedef, one could also do: PULONG Reason = &var; */
In the function code, the asterisk syntax: "*Reason", dereferences the pointer: it makes you obtain access to the underlying contents (for example, 'var') pointed by the pointer, so that you can modify it.
Posted: Tue Feb 07, 2017 8:09 pm
Okay, I get that much, so if the pointer exists and is not null, it's value gets cleared to zero, otherwise nothing happens.
Now I have questions. What does the asterisk (*) mean? Does it mean to work with the value of the pointer as opposed to the pointer? (Okay, I guessed right.) And what is the role of the parenthesis? I thought those were used as mathematical separators.
I was going to ask about the difference between ULONG, PULONG, etc. But I figured them out and then found this:
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
So ULONG is unsigned long, and PULONG is unsigned long pointer, and both are 32-bits (0-4294967295).
Posted: Tue Feb 07, 2017 8:35 pm
That snippet as a single line of code might actually be breaking our coding guidelines. It's the equivalent of the following.
It's two separate operations, an if check to see if Reason is non-zero (it's fairly common to omit the == 0 part of these checks in C/C++, especially when dealing with pointers), and an if Reason is a valid pointer and not NULL, an assignment operation to set the value Reason points to to 0. * means dereference in C. When you use pointers, using the raw variable like Reason means you're manipulating the memory address. Using * means you are manipulating the value that is held at that address.
We generally try to discourage one-liners like that because it can make debugging a bit less intuitive than it should be, wherein it is not immediately obvious whether a bugcheck is due to the condition test or due to the code that is being conditioned.
Posted: Tue Feb 07, 2017 8:44 pm
Little snippets of information like this might slowly turn us lowly scriptors out there into potential C programmers (bit by bit). How about passing and continuing these sort of snippets in another thread?
Posted: Tue Feb 07, 2017 9:33 pm
dizt3mp3r wrote:Little snippets of information like this might slowly turn us lowly scriptors out there into potential C programmers (bit by bit). How about passing and continuing these sort of snippets in another thread?
Agreed. Maybe a thread either in Dev Help or even OT. Where would be the best to start such a thread?
I was going to ask what single and double logical operators mean, but I just discovered that two in a row means to do a short-circuit version. If you don't need the traditional AND (generally used for mathematical purposes, while it can also be used to compare two conditions and run a code path if both are true), then you can use a short-circuit and to where only the first condition is tested if it fails (more appropriate for determining code paths than looking for common bits). I discovered that back when I coded in QB and real mode x86 assembly, when I found that tests on the same line using AND did not produce the same machine code as nested IF statements. While the AND statements looked shorter, they produced more machine code and perhaps took longer to run than nested IFs. For determining a code path, that's why short-circuit ANDs are generally preferable to traditional ANDs. There's no need to test all conditions on failure, when you can skip all the remaining tests since AND requires all conditions to be true, and doing more tests won't make the first condition change. So in code paths, assigning values to the results and doing a logical comparison on the results would typically be less preferable to simply ordering and nesting the tests, using conditional jumps.
Posted: Tue Feb 07, 2017 9:57 pm
Also of note -
is equal to
because, basically, NULL in C means 0 .
There are different ways to represent a null pointer in C++, but that's way beyond this snippet.
 longer answer: the standard actually says that the representation is implementation-defined, but is guaranteed to compare equal to 0.