In this reprinted #altdevblogaday in-depth piece, Gamer Camp's Alex Darby continues his series on a C/C++ Low Level Curriculum by examining three built-in looping structures. Welcome to the ninth post in this C/C++ low level curriculum series I've been doing. It's been a long time since post 8 (way longer than I thought it was), a fact I can only apologize for. My 3-year-old son stopped having a nap in the afternoon in late April, and it's totally ruined my productivity… This post covers the 3 built-in looping control structures while, do-while, and for as well as the manual if-goto loop (old school!); as usual, we look in some detail at the assembly generated by the compiler looks like. Did I forget about the new range-based-for loop that was added in the C++11 standard? Nope. If you have access to a C++11 compliant compiler you're more than welcome to look at that yourself – think of it as homework… Here are the backlinks for preceding articles in the series (warning: it might take you a while, the first few are quite long):
A Low Level Curriculum for C and C++
C / C++ Low Level Curriculum part 2: Data Types
C / C++ Low Level Curriculum Part 3: The Stack
C / C++ Low Level Curriculum: More Stack
C / C++ Low Level Curriculum Part 5: Even More Stack
C / C++ Low Level Curriculum Part 6: Conditionals
C / C++ Low Level Curriculum Part 7: More Conditionals
C / C++ Low Level Curriculum Part 8: Looking at optimized assembly
A brief history of looping
It occurred to me that a sensible order to cover the looping constructs of the C/C++ language might be to address them in the order in which they were introduced into the language. A couple of years back a friend showed me a brilliant website / article that covered the evolution of the C programming language. It was very interesting, and from what I can remember, contained information on the order in which the various features of the C compiler were added – including which looping construct came first. I tried to find it on t' internet, but failed. Feel free to link me up in a comment if you happen to know where it is… Since I couldn't find the article /website in question I've decided to cover them in the order of the amount of work they do automatically for the programmer, which in my opinion is: if-goto, while, do-while, and finally for. This seems to me to be a sensible order for two reasons; firstly because it's likely to be the order in which they were introduced into programming languages, and secondly because the concepts encapsulated by these constructs sort of build on each other in that order.
if-goto
From our previous excursions into the land of assembly we are already familiar with the concept of jumping the execution address, and with the concept of 'conditional jumping' (i.e. conditionally changing the execution address). The most direct way to loop the execution of a piece of code several times (as opposed to the simplest to type) is to use the high level keywords that correspond to these assembly level concepts. We are already familiar with the keyword if but we've not really covered goto – possibly the most maligned of all the language features of C/C++, and almost certainly the most banned by corporate coding standards. Personally I don't think that goto is inherently more dangerous than (for example) operator overloading; but, the purpose of this article is not to discuss goto – if you're interested here's the Wikipedia page which contains a fair amount of detail (and links to) on the arguments for and against it. The purpose of this article is not to discuss the merits of goto or, for that matter, operator overloading so let's get on with it. Here's the first code snippet (see the previous article for how to set up a project that will just accept this code…)
#include "stdafx.h"
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
int main(int argc, char* argv[])
{
int k_aiData[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int iSum = 0;
int iLoop = 0;
LoopStart:
if( iLoop < ARRAY_SIZE(k_aiData) )
{
iSum += k_aiData[ iLoop ];
++iLoop;
goto LoopStart;
}
return 0;
}You should be able to see that this code is simply looping over the values in the array k_aiData and summing them, other than the use of if and goto it's essentially a standard loop to iterate an array. The pre-processor macro ARRAY_SIZE that I've used here is a simple way to make dealing with statically allocated arrays less error prone. Essentially we could initialize the array k_aiData with any number of elements we wanted to and the rest of the code would still just work. There are simple ways to achieve this in a type safe manner using templates too, but I chose to use a macro here because a readable version of the code takes up less vertical space than the template. If you are wondering why I am not incrementing iLoop inside the square brackets, this is so that the high level code that is doing the work of the loop is identical across all code snippets. If you are also wondering why I am using the prefix as opposed to postfix version of operator++ then well done to you – award yourself 6.29 paying attention points. In this case it makes no difference to the assembly generated, but in these days of operator overloading it's generally better to use the prefix version as a point of good practice – unless of course you require postfix behavior (the first comment on the first answer to this question on Stack Overflow should prove illuminating if you don't know what implications of the different behaviors are). Since we're using two keywords that have a very clear relationship to assembly level concepts, it's reasonable to assume that the disassembly for this code will be pretty much as we wrote it at the high level. As we all know, we should never assume; so let's check our assumptions. Here is the debug x86 disassembly for the looping section:
11: LoopStart: 12: if( iLoop < ARRAY_SIZE(k_aiData) ) 00BB1299 cmp dword ptr [ebp-2Ch],8 00BB129D jae LoopStart+1Eh (0BB12B7h) 13: { 14: iSum += k_aiData[ iLoop ]; 00BB129F mov eaxdword ptr
No tags.

