C Coding Basics

All development related issues welcome

Moderator: Moderator Team

PurpleGurl
Posts: 1790
Joined: Fri Aug 07, 2009 5:11 am
Location: USA

C Coding Basics

Post by PurpleGurl »

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.
Last edited by PurpleGurl on Wed Feb 08, 2017 1:48 pm, edited 1 time in total.
User avatar
Black_Fox
Posts: 1584
Joined: Fri Feb 15, 2008 9:44 pm
Location: Czechia

Re: C Coding Basics

Post by Black_Fox »

Please correct me if I'm wrong; I believe that | and & operators should be called "bitwise and/or" rather than "logical and/or".
User avatar
dizt3mp3r
Posts: 1874
Joined: Mon Jun 14, 2010 5:54 pm

Re: C Coding Basics

Post by dizt3mp3r »

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.
PurpleGurl
Posts: 1790
Joined: Fri Aug 07, 2009 5:11 am
Location: USA

Re: C Coding Basics

Post by PurpleGurl »

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".
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.

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.
User avatar
dizt3mp3r
Posts: 1874
Joined: Mon Jun 14, 2010 5:54 pm

Re: C Coding Basics

Post by dizt3mp3r »

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.
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.
PurpleGurl
Posts: 1790
Joined: Fri Aug 07, 2009 5:11 am
Location: USA

Re: C Coding Basics

Post by PurpleGurl »

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.
User avatar
dizt3mp3r
Posts: 1874
Joined: Mon Jun 14, 2010 5:54 pm

Re: C Coding Basics

Post by dizt3mp3r »

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...
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.
Z98
Release Engineer
Posts: 3379
Joined: Tue May 02, 2006 8:16 pm
Contact:

Re: C Coding Basics

Post by Z98 »

sdk/lib/rtl/heap.c:2020

Code: Select all

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.

Bonus question: How does

Code: Select all

~((1 << ((ULONG)Index & 0x1f)) - 1)
act as a mask?
erkinalp
Posts: 861
Joined: Sat Dec 20, 2008 5:55 pm
Location: Izmir, TR

Re: C Coding Basics

Post by erkinalp »

Code: Select all

~((1 << ((ULONG)Index & 0x1f)) - 1)
Two's complement specific. Will not work on one's complement ports.
-uses Ubuntu+GNOME 3 GNU/Linux
-likes Free (as in freedom) and Open Source Detergents
-favors open source of Windows 10 under GPL2
PurpleGurl
Posts: 1790
Joined: Fri Aug 07, 2009 5:11 am
Location: USA

Re: C Coding Basics

Post by PurpleGurl »

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.
It dereferences the FreeListsInUse pointer and increments its value by one. Right?
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.
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.

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.
Z98
Release Engineer
Posts: 3379
Joined: Tue May 02, 2006 8:16 pm
Contact:

Re: C Coding Basics

Post by Z98 »

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.
PurpleGurl
Posts: 1790
Joined: Fri Aug 07, 2009 5:11 am
Location: USA

Re: C Coding Basics

Post by PurpleGurl »

Z98 wrote:It is actually not incrementing the value. Order of operation precedence applies here.
So it is incrementing the address and then retrieving the value of the incremented pointer?

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
What is happening is that in the second line, the value is assigned and then the host variable is incremented. So b remains 0 because it gets copied from a before a is incremented. In the third line, a starts off as being 1, then it is incremented to 2 and then assigned.
Z98
Release Engineer
Posts: 3379
Joined: Tue May 02, 2006 8:16 pm
Contact:

Re: C Coding Basics

Post by Z98 »

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:

Code: Select all

FreeListsInUseUlong = *FreeListsInUse++ & ~((1 << ((ULONG)Index & 0x1f)) - 1);
can actually be be expressed as this:

Code: Select all

FreeListsInUseUlong = *FreeListsInUse & ~((1 << ((ULONG)Index & 0x1f)) - 1);
++FreeListsInUse;
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:

Code: Select all

(*FreeListsInUse)++;
And if you wanted to increment the pointer and then dereference it, you would need to do this:

Code: Select all

*(++FreeListsInUse);
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. :P
User avatar
dizt3mp3r
Posts: 1874
Joined: Mon Jun 14, 2010 5:54 pm

Re: C Coding Basics

Post by dizt3mp3r »

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 :(
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.
PurpleGurl
Posts: 1790
Joined: Fri Aug 07, 2009 5:11 am
Location: USA

Re: C Coding Basics

Post by PurpleGurl »

So I get it, and to express it in assembly, it might be similar to this (at least in real mode):

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.
To be more accurate, I probably should have used 32-bit registers. So one would replace with EAX and EBX.
Last edited by PurpleGurl on Mon Feb 13, 2017 7:45 pm, edited 1 time in total.
Post Reply

Who is online

Users browsing this forum: No registered users and 11 guests