C Coding Basics
Moderator: Moderator Team
-
- Posts: 1790
- Joined: Fri Aug 07, 2009 5:11 am
- Location: USA
C Coding Basics
As everyone knows, the primary coding languages of ROS are C and C++, with some assembly used in some intimate or critical places. A number of us look at the repository logs and follow the progress. As we look at it, we often have questions.
Now, to start this thread, I'll first try to sum up this other thread: viewtopic.php?f=9&t=16234
Over there, it was suggested to start a more general thread for discussing tidbits of C and what code snippets mean. That gives more context and helps more enthusiasts and testers to try their hand at coding. I initially asked questions in the above listed thread about a code snippet I saw. Then I wanted to know what various symbols meant. The thread uncovered the following:
-- An asterisk in front of a pointer means to dereference a pointer and deal with its value.
-- An ampersand before a variable is used to get the variable's address rather than its value.
-- A single ampersand by itself means to do a bitwise AND. So if a single bit is false or zero, then it is false or zero in the result. So if you AND 2 (00000010) with 1 (00000001), you get 0 (00000000) since there are not corresponding bits that are both 1. However ANDing 3 (00000011) with 1 (00000001) would give you a decimal 1 (both a decimal 1 and a decimal 3 have the first bit high), and ANDing a decimal 3 with a decimal 2 will give you a decimal 2 (since bit two is high in both but not both high with any of the other bits).
-- Two ampersands by themselves (&&) means to do a short-circuited AND. As opposed to using AND to do a masking operation, this is used when evaluating to see if two or more conditions are true and not evaluating any longer once a condition is found to be false. In languages that don't have a short-circuited AND operator, you can still do the same thing using nested conditional operations. In Quickbasic, one could put IF....THEN clauses inside of IF....THEN clauses, and only do the intended action inside the innermost clause, causing the deeper conditionals to not execute should outer conditionals fail. That would likely produce smaller and faster code than using AND to stack conditions on a single line. In assembly, the way to do similar to a short-circuited AND is to use conditional jumps to where earlier conditionals skip around the other conditionals if they are not true, and then if all the conditionals are true, it falls into the code that works if all conditionals in that group are true.
-- A single pipe symbol means to do a bitwise OR. So if one bit is true, then the bit is true in the result. So ORing decimal 3 (00000011 b) with 0 (00000000 b) yields 3 since both of the lowest 2 bits are high in at least one of the numbers. I used this when I wanted to capitalize the ASCII value of a digit. So I would simply OR the bit mask of 00100000 or whatever it was to make sure that one bit was turned on. And I didn't bother testing the variable first. Since why spend up to 3 cycles on a conditional jump that passes (and reset the prefetch queue on older x86 CPUs) and 1 if it fails, if doing OR in a CPU register only takes one cycle? So 3 cycles if true and 2 if false when you can just presumptively do the OR without testing and only consume a cycle regardless.
-- A double pipe symbol (||) means to do a short-circuited OR. So when comparing two or more conditions, execution of the group of conditions stops once any condition is found to be true. So if you only care if ONE condition is true, there is no need to test them all once you find one to be true. This works similar to the short-circuited AND described above, but evaluations stop on the first true rather than the first false, and the code that is executed when any condition is true would be executed (and nothing is done but go to the next instruction past the block if all are false).
Then there are data types. I found that all the answers about what they mean and their sizes could be found here.
Now, to start this thread, I'll first try to sum up this other thread: viewtopic.php?f=9&t=16234
Over there, it was suggested to start a more general thread for discussing tidbits of C and what code snippets mean. That gives more context and helps more enthusiasts and testers to try their hand at coding. I initially asked questions in the above listed thread about a code snippet I saw. Then I wanted to know what various symbols meant. The thread uncovered the following:
-- An asterisk in front of a pointer means to dereference a pointer and deal with its value.
-- An ampersand before a variable is used to get the variable's address rather than its value.
-- A single ampersand by itself means to do a bitwise AND. So if a single bit is false or zero, then it is false or zero in the result. So if you AND 2 (00000010) with 1 (00000001), you get 0 (00000000) since there are not corresponding bits that are both 1. However ANDing 3 (00000011) with 1 (00000001) would give you a decimal 1 (both a decimal 1 and a decimal 3 have the first bit high), and ANDing a decimal 3 with a decimal 2 will give you a decimal 2 (since bit two is high in both but not both high with any of the other bits).
-- Two ampersands by themselves (&&) means to do a short-circuited AND. As opposed to using AND to do a masking operation, this is used when evaluating to see if two or more conditions are true and not evaluating any longer once a condition is found to be false. In languages that don't have a short-circuited AND operator, you can still do the same thing using nested conditional operations. In Quickbasic, one could put IF....THEN clauses inside of IF....THEN clauses, and only do the intended action inside the innermost clause, causing the deeper conditionals to not execute should outer conditionals fail. That would likely produce smaller and faster code than using AND to stack conditions on a single line. In assembly, the way to do similar to a short-circuited AND is to use conditional jumps to where earlier conditionals skip around the other conditionals if they are not true, and then if all the conditionals are true, it falls into the code that works if all conditionals in that group are true.
-- A single pipe symbol means to do a bitwise OR. So if one bit is true, then the bit is true in the result. So ORing decimal 3 (00000011 b) with 0 (00000000 b) yields 3 since both of the lowest 2 bits are high in at least one of the numbers. I used this when I wanted to capitalize the ASCII value of a digit. So I would simply OR the bit mask of 00100000 or whatever it was to make sure that one bit was turned on. And I didn't bother testing the variable first. Since why spend up to 3 cycles on a conditional jump that passes (and reset the prefetch queue on older x86 CPUs) and 1 if it fails, if doing OR in a CPU register only takes one cycle? So 3 cycles if true and 2 if false when you can just presumptively do the OR without testing and only consume a cycle regardless.
-- A double pipe symbol (||) means to do a short-circuited OR. So when comparing two or more conditions, execution of the group of conditions stops once any condition is found to be true. So if you only care if ONE condition is true, there is no need to test them all once you find one to be true. This works similar to the short-circuited AND described above, but evaluations stop on the first true rather than the first false, and the code that is executed when any condition is true would be executed (and nothing is done but go to the next instruction past the block if all are false).
Then there are data types. I found that all the answers about what they mean and their sizes could be found here.
Last edited by PurpleGurl on Wed Feb 08, 2017 1:48 pm, edited 1 time in total.
Re: C Coding Basics
Please correct me if I'm wrong; I believe that | and & operators should be called "bitwise and/or" rather than "logical and/or".
Re: C Coding Basics
Very informative - I am learning.
Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.
-
- Posts: 1790
- Joined: Fri Aug 07, 2009 5:11 am
- Location: USA
Re: C Coding Basics
Thank you, and using logical there would be ambiguous. We should try to use the correct terminology so we can all know what we are discussing. I think of things in more of a global, impressionistic sort of way. That means I won't always use the correct terms, so it is helpful to be told what they are.Black_Fox wrote:Please correct me if I'm wrong; I believe that | and & operators should be called "bitwise and/or" rather than "logical and/or".
That's a lesson to learn when it comes to troubleshooting and using a search engine to find solutions. Nearly every PC problem you will encounter has been experienced by others, and it can be hard to find discussion on those online unless you search using the correct terminology. So one might have to guess, and when pages using different terms come up, then repeat the search using those. Error messages are generally easier to search as most who write about them will list them verbatim. Speaking of which, as a side note, it is only useful to search on the first part of a blue screen message, and not the 128-bit address in parenthesis that follows. I say that because we are different internally from Windows. So while the error codes should be the same as with Windows, the address where the exception or crash occurred will be different from Windows. Someone put up a blue screen pic or code the other day or so, and I wasn't having luck searching for it at first. Then I included up to the error number without giving the 4 32-bit hex numbers that followed and found that the error message was about problems accessing the system registry. So unless their drive was going bad, it was likely either their VM or BIOS settings, or ROS just not working on their machine (maybe driver issues).
Last edited by PurpleGurl on Sat Mar 18, 2017 7:38 pm, edited 1 time in total.
Re: C Coding Basics
I am happy just to have the coding pointers revealed. If I understand then good if I don't then I can do some digging with the information provided.
More please.
Many of us come from scripting backgrounds without formal training, from the point of view of an average javascript/PHP/VB6/DCL scripter it is all "grist to the mill" as it is all thoroughly new to me, both in the language intricacies and the context of o/s development . I understand the lessons when it they explained as long as the reasoning and potential usage is pointed out. Real life examples are always useful.
More please.
Many of us come from scripting backgrounds without formal training, from the point of view of an average javascript/PHP/VB6/DCL scripter it is all "grist to the mill" as it is all thoroughly new to me, both in the language intricacies and the context of o/s development . I understand the lessons when it they explained as long as the reasoning and potential usage is pointed out. Real life examples are always useful.
Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.
-
- Posts: 1790
- Joined: Fri Aug 07, 2009 5:11 am
- Location: USA
Re: C Coding Basics
Here are other bitwise operations and their operators.
Here are all the operators in C and C++.
Here is information on advanced code tuning and optimizations.
Here are all the operators in C and C++.
Here is information on advanced code tuning and optimizations.
Re: C Coding Basics
Lovely info . for reference but real-life examples in context (and one at a time) are always easier to absorb. We could always just point to the top of wikipedia and then request they start reading downward. Those that have ambiguity and intricacies of usage are the most interesting. Also, some examples of info. regarding such usage within ReactOS?
Would be nice...
Would be nice...
Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.
Re: C Coding Basics
sdk/lib/rtl/heap.c:2020
An "optimization" by Aleksey Bragin wherein he uses pointer and bit twiddling magic in order to mask out all entries in a list that are smaller than a requested size. Extremely clever, and utterly incomprehensible at first glance. So, homework time.
Question: What does *FreeListsInUse++ do.
Bonus question: How does
act as a mask?
Code: Select all
FreeListsInUseUlong = *FreeListsInUse++ & ~((1 << ((ULONG)Index & 0x1f)) - 1);
Question: What does *FreeListsInUse++ do.
Bonus question: How does
Code: Select all
~((1 << ((ULONG)Index & 0x1f)) - 1)
Re: C Coding Basics
Code: Select all
~((1 << ((ULONG)Index & 0x1f)) - 1)
-uses Ubuntu+GNOME 3 GNU/Linux
-likes Free (as in freedom) and Open Source Detergents
-favors open source of Windows 10 under GPL2
-likes Free (as in freedom) and Open Source Detergents
-favors open source of Windows 10 under GPL2
-
- Posts: 1790
- Joined: Fri Aug 07, 2009 5:11 am
- Location: USA
Re: C Coding Basics
It dereferences the FreeListsInUse pointer and increments its value by one. Right?Z98 wrote:sdk/lib/rtl/heap.c:2020
FreeListsInUseUlong = *FreeListsInUse++ & ~((1 << ((ULONG)Index & 0x1f)) - 1);
An "optimization" by Aleksey Bragin wherein he uses pointer and bit twiddling magic in order to mask out all entries in a list that are smaller than a requested size. Extremely clever, and utterly incomprehensible at first glance. So, homework time.
Question: What does *FreeListsInUse++ do.
The tilde means bitwise not. 0x1f is 31 (decimal) or 00011111 binary. The 5 lowest bits are high. However, it is unsigned long, which also means a doubleword or 32-bit integer. What is tricky here is that the other 27 bits of the mask number are low. ANDing with 1 keeps the existing 1 bits as 1. So the top 27 bits are turned off, meaning the result of ANDing 0x1f can never be greater than 0x1f (31 decimal), nor less than 0 since the type is unsigned. I'm not sure of the 1<< part though I think that means to shift everything to the left by 1 bit, essentially doubling the result. Then 1 is subtracted from that. Then the tilde flips all the bits and gives the final result for that chunk.Bonus question: How does ~((1 << ((ULONG)Index & 0x1f)) - 1) act as a mask?
Note, that ~ is not a minus sign, it's a tilde. For some reason it's not rendering properly, at least for me.
Thus answering the big question, since the upper bits are all high, doing the bitwise AND with the more complex chunk means the top 26 bits stay on.
Re: C Coding Basics
It is actually not incrementing the value. Order of operation precedence applies here.
As an addendum, I will explain it tomorrow if no one comes up with an answer, but I'd prefer to give others a chance to exercise their brains a bit first.
As an addendum, I will explain it tomorrow if no one comes up with an answer, but I'd prefer to give others a chance to exercise their brains a bit first.
-
- Posts: 1790
- Joined: Fri Aug 07, 2009 5:11 am
- Location: USA
Re: C Coding Basics
So it is incrementing the address and then retrieving the value of the incremented pointer?Z98 wrote:It is actually not incrementing the value. Order of operation precedence applies here.
The rationale is that you could have typed *(FreeListsInUse++). I didn't know that prefix and postfix variants had different binding strengths. Thus ++ is of equal precedence if the prefix form were used, which would mean the value is incremented, while the postfix form means the address is incremented.
I found this snippet online and was confused at first.
Code: Select all
int a=0,b,c;
b=a++; //b=0
c=++a; //b=2
Re: C Coding Basics
Still not quite right. What Aleksey did was a fairly subtle piece of pointer arithmetic that I'm personally ambivalent about since it is not obvious at all what it does unless you actually think about it and know in detail things like operator precedence and whatnot. It is clever though, and can serve as a teaching moment.
What that snippet of code is doing is dereferencing (basically extracting the value) of the pointer, and after the dereference, increment the pointer's reference. So the following:
can actually be be expressed as this:
Because ++ is used as a postfix operation, it will be applied AFTER the access of the FreeListsInUse. In this instance, the access to FreeListsInUse was a dereference with *, so the address used to extract the value was the address before the increment operation takes place. But because the increment operation ONLY applies to the FreeListsInUse pointer, it is completely self-contained and has no effect on the bitmask operation that makes up the rest of the line. As I said, clever, and very non-obvious. If you wanted to increment the value itself, you would need do this:
And if you wanted to increment the pointer and then dereference it, you would need to do this:
Pointer magic. Trying to be too clever with this sort of thing can and will get you in trouble, and even experienced programmers will sometimes make mistakes when doing stuff like this. It's why in general I prefer not to write code like this, but to each their own. And of course, it is still a useful example for teaching. Just don't let me catch any of you newbies trying to pull pointer magic like this.
What that snippet of code is doing is dereferencing (basically extracting the value) of the pointer, and after the dereference, increment the pointer's reference. So the following:
Code: Select all
FreeListsInUseUlong = *FreeListsInUse++ & ~((1 << ((ULONG)Index & 0x1f)) - 1);
Code: Select all
FreeListsInUseUlong = *FreeListsInUse & ~((1 << ((ULONG)Index & 0x1f)) - 1);
++FreeListsInUse;
Code: Select all
(*FreeListsInUse)++;
Code: Select all
*(++FreeListsInUse);
Re: C Coding Basics
I am glad that I deal with languages that do not provide access to memory addresses, relieving me of that burden of knowledge that I would almost certainly abuse.
Having said that, I really appreciate the insight you are providing. If anything it just makes me realise how far my coding skills are - from being useful
Having said that, I really appreciate the insight you are providing. If anything it just makes me realise how far my coding skills are - from being useful
Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.
-
- Posts: 1790
- Joined: Fri Aug 07, 2009 5:11 am
- Location: USA
Re: C Coding Basics
So I get it, and to express it in assembly, it might be similar to this (at least in real mode):
To be more accurate, I probably should have used 32-bit registers. So one would replace with EAX and EBX.
Code: Select all
mov AX, [BX] ;BX register used as pointer, the value is copied into register
mov FreeListsInUseUlong, AX ;first since memory to memory accesses are not allowed.
Inc BX ;Increment location stored in register used as pointer.
Last edited by PurpleGurl on Mon Feb 13, 2017 7:45 pm, edited 1 time in total.
Who is online
Users browsing this forum: No registered users and 29 guests