Understanding for loops 10-09-2017, 03:00 PM
#1
Loops are one of those things that sort of get people. In C, you're told that there are a few:
while
do-while
for
foreach (this one is a trick)
In reality, this isn't true. Some loops are made up of other loops, some loops don't even exist at all.
Let's take a look at the basic syntax of a for loop in C:
This probably looks a little different from what you're used to seeing (see spoiler), but I chose to write it this way for a reason.
I want to go into the reasons I chose to write it that way, in due time, but for now let's try to understand the reasons for using a for loop.
You're told that you need a for loop whenever you want to repeat steps over a known portion of data, like say if you had a split array of strings:
and you wanted to put them all together, you could use a for loop for that:
To some, this seems like a good response, however it can be done in a more simple way. See, for loops can do a lot more than just iterate over something. A common misconception is that they have to have some initialization value, and some increment task to do, but that's not true.
Let's look at another example. From time to time, programmers need an infinite loop. You may need one because thread X is waiting on data from thread Y, which will send SIGHUP to X when it's complete. In this case, you don't want thread X to die while it waits, so it can't return out. So what you would do is add a signal handler to the thread that dispatches it's CPU time whenever it gets SIGHUP. Then, at the end of the task handler you would leave an infinite loop. A lot of people would write it like this:
While this will achieve the same results you want, it will also use more CPU time. This code does 2 things:
compares 0=0
if true, does nothing
repeat
You can do the same thing with a for loop:
this loop only does one thing: nothing. There is no setup, condition, or post-op here. Your compiler will generate the following assembly code for this loop:
the while loop will generate the following, if it's not intelligent:
if it is intelligent, it will come up with the same answer as the for loop. Why is this, they clearly aren't the same?
Turns out the for loop is that one that doesn't really exist. The reason I labeled the parts the way I did is so that it would make sense when I rearranged it like this:
So, for loops compile into while loops, that's pretty neat to know. Now you can go ahead and take off that whole increment/init restriction. For loops are just a block method shorthand, you can use them like they're specific task inline functions, as long as you use the right format. (variables defined before they're used, statements don't use conditions, etc.
Let's look at one last example, just to show you what you can use them for. Finding the tail end of a linked list.
Structure:
while loop:
This looks messy to me, and I wouldn't understand it right away without comments. Let's take a look at the for loop version:
That looks much better., don't you think?
Also, keep in mind that a semicolon is a statement, so your loop doesn't actually have to have any body to it.
Sorry this is such a short one, I'll go into more depth with other loops if people want, I just remembered that it was interesting and figured I'd write it.
Fun fact to get people thinking:
in C++, there are only 2 differences between a class and a struct, and the most important difference is that they are spelled differently.
while
do-while
for
foreach (this one is a trick)
In reality, this isn't true. Some loops are made up of other loops, some loops don't even exist at all.
Let's take a look at the basic syntax of a for loop in C:
Code:
for (setup; condition; post-op) statement
Spoiler:
You're told that you need a for loop whenever you want to repeat steps over a known portion of data, like say if you had a split array of strings:
Code:
[this, is, a, test]
Code:
void concatenateList(char *out, char * const * in, int length)
{
int index;
for (index = 0; index < length; ++index)
sprintf(out + strlen(out), "%s", in[index]);
}
Let's look at another example. From time to time, programmers need an infinite loop. You may need one because thread X is waiting on data from thread Y, which will send SIGHUP to X when it's complete. In this case, you don't want thread X to die while it waits, so it can't return out. So what you would do is add a signal handler to the thread that dispatches it's CPU time whenever it gets SIGHUP. Then, at the end of the task handler you would leave an infinite loop. A lot of people would write it like this:
Code:
while (true) { }
compares 0=0
if true, does nothing
repeat
You can do the same thing with a for loop:
Code:
for (;;);
Code:
jmp $
Code:
xor ax, ax
test ax
je -8
Turns out the for loop is that one that doesn't really exist. The reason I labeled the parts the way I did is so that it would make sense when I rearranged it like this:
Code:
setup
while (condition)
{
statement
post-op
}
So, for loops compile into while loops, that's pretty neat to know. Now you can go ahead and take off that whole increment/init restriction. For loops are just a block method shorthand, you can use them like they're specific task inline functions, as long as you use the right format. (variables defined before they're used, statements don't use conditions, etc.
Let's look at one last example, just to show you what you can use them for. Finding the tail end of a linked list.
Structure:
Code:
struct llist
{
int value;
struct llist *next;
};
struct llist *head;
while loop:
Code:
struct llist *tail = head; //temporary
if (tail != NULL)
while (tail->next != null)
tail = tail->next;
//tail is now at end of list
Code:
struct llist *tail;
for (tail = head; tail != NULL && tail->next != NULL; tail = tail->next);
//tail is now at end of list
Also, keep in mind that a semicolon is a statement, so your loop doesn't actually have to have any body to it.
Sorry this is such a short one, I'll go into more depth with other loops if people want, I just remembered that it was interesting and figured I'd write it.
Fun fact to get people thinking:
in C++, there are only 2 differences between a class and a struct, and the most important difference is that they are spelled differently.