Emulating the foreach Keyword

In last week’s Lesson, I covered how to obtain the number of elements in an array. This process is the first step to emulating the foreach keyword in the C language.

The best approach is to divide the array size in memory by the size of its first element, which presents a consistent way to obtain the element count. Otherwise, a separate foreach() function must be crafted for each data type.

Here is the expression: sizeof(a)/sizeof(a[0]), where a is an array of any data type.

To prove that this approach works, I created the following code. It identifies the size of array f[] and spews out the elements based on the size value calculated:

2021_01_02-Lesson-a.c

#include <stdio.h>

int main()
{
    float f[] = { 1.4, 5.7, 9.0, 22.7, 88.8 };
    int size,x;

    size = sizeof(f)/sizeof(f[0]);
    for( x=0; x<size; x++ )
        printf("%.1f\n",f[x]);

    return(0);
}

The foreach part of the code is handled by the for loop at Line 9. Here is the output:

1.4
5.7
9.0
22.7
88.8

At this point, the goal is to create the foreach equivalent. Unfortunately, it can’t be a function. That’s because passing an array to a function passes the array’s address, not the full array. So any sizeof statement used within the function returns the size of the array’s address (a pointer, usually 8 bytes), not the size of the array in memory.

No, to properly emulate a foreach() keyword in C, you must create a macro. It combines both Lines 8 and 9 from the preceding example:

#define foreach(a,b) for(int a=0;a<(sizeof(b)/sizeof(b[0]));a++)

Variable a is declared as an int within the macro. The rest of the assignment is a for loop, with the array size calculation as its middle part. Variable b represents the array.

Obviously, this construction isn’t identical to a true foreach statement, nor does it match any of the alternatives I’ve seen presented on various programming websites. Despite my best efforts, it works within its given parameters: The second argument must be an array and the first argument is an integer variable not otherwise used in the function:

2021_01_02-Lesson-b.c

#include <stdio.h>

#define foreach(a,b) for(int a=0;a<(sizeof(b)/sizeof(b[0]));a++)

int main()
{
    float f[] = { 1.4, 5.7, 9.0, 22.7, 88.8 };

    foreach(x,f)
        printf("%.1f\n",f[x]);

    return(0);
}

The output is identical to the first example.

This approach also works for creating simple repeating loops. For example:

2021_01_02-Lesson-c.c

#include <stdio.h>

#define foreach(a,b) for(int a=0;a<(sizeof(b)/sizeof(b[0]));a++)

int main()
{
    char c[] = "abcdefg";

    foreach(x,c)
        puts("Whee!");

    return(0);
}

You need not do anything with the variable; just let the loop repeat, as shown in this output:

Whee!
Whee!
Whee!
Whee!
Whee!
Whee!
Whee!
Whee!

I would hope that a future update to C — a significant update — might include such new keywords as foreach and perhaps conveniences from other languages. Still, venerable C has survived without these additions. Obviously, anything you can think of can be programmed one way or the other. All you need is motivation and time.

Leave a Reply