131

Almost all languages have a foreach loop or something similar. Does C have one? Can you post some example code?

MD XF
  • 7,860
  • 7
  • 40
  • 71
Question
  • 1,419
  • 3
  • 14
  • 6

14 Answers14

221

C doesn't have a foreach, but macros are frequently used to emulate that:

#define for_each_item(item, list) \
    for(T * item = list->head; item != NULL; item = item->next)

And can be used like

for_each_item(i, processes) {
    i->wakeup();
}

Iteration over an array is also possible:

#define foreach(item, array) \
    for(int keep = 1, \
            count = 0,\
            size = sizeof (array) / sizeof *(array); \
        keep && count != size; \
        keep = !keep, count++) \
      for(item = (array) + count; keep; keep = !keep)

And can be used like

int values[] = { 1, 2, 3 };
foreach(int *v, values) {
    printf("value: %d\n", *v);
}

Edit: In case you are also interested in C++ solutions, C++ has a native for-each syntax called "range based for"

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 1
    If you've got the "typeof" operator (gcc extension; pretty common on many other compilers) you can get rid of that "int *". The inner for loop becomes something like "for(typeof((array)+0) item = ..." Then you can call as "foreach( v, values ) ..." – leander Aug 06 '09 at 04:46
  • Why do we need two for loops in the array example? How about this: `#define foreach(item, array) int count=0, size=sizeof(array)/sizeof(*(array)); for(item = (array); count != size; count++, item = (array)+count)` One problem that I can see is that variables count and size live outside the for loop, and might cause a conflict. Is this the reason you use two for loops? [code pasted here(http://pastebin.com/immndpwS )] – Lazer May 09 '10 at 11:23
  • 3
    @eSKay yes consider `if(...) foreach(int *v, values) ...` . If they are outside the loop it expands to `if(...) int count = 0 ...; for(...) ...;` and will break. – Johannes Schaub - litb May 09 '10 at 11:37
  • What's the purpose of the `keep` variable? – fredoverflow Feb 15 '12 at 10:30
  • I have some questions. Would this break if the user did foreach(int *keep, keeps)? Also, in the inner loop, what does the parenthesis around array do? – Russell Apr 27 '12 at 14:49
  • #define for_each_item(item, listHead) \ for(T * item = listHead->next; item != NULL; item = item->next) – Brans Ds Jul 01 '14 at 09:07
  • @Russell yes unfortunately that would break. If you use this for real code, you best should use weird names for `keep` and the others. – Johannes Schaub - litb Jul 01 '14 at 20:21
  • @JohannesSchaub-litb: It would be better if you update your answer to include range based for loop introduced by C++11. – Destructor Sep 21 '15 at 10:11
  • Recommend `int` --> `size_t` in `for(size_t keep = 1, \ ...` – chux - Reinstate Monica Oct 16 '15 at 15:52
  • I was having a little trouble understanding your two `keep = !keep` statements. I think the following works just as well and is (in my opinion) a little clearer: `#define array_elements(arr) ( sizeof(arr) / sizeof(arr[0]) )` `#define array_for(item, array) for(unsigned int cont=1, i=0; i – rem Sep 26 '16 at 09:56
  • 1
    @rem it does not break the outer loop if you use "break" – Johannes Schaub - litb Sep 26 '16 at 11:05
  • 1
    @rem you can however simplify my code if you change the inner "keep = !keep" into "keep = 0". I liked the "symmetry" so i just used negation and not straight assignment. – Johannes Schaub - litb Sep 26 '16 at 11:12
  • I realised you could also eliminate the nested loop completely by incrementing the pointer in stead of a separate iterator: `#define array_for(item, array) for(typeof(array[0])* item=array; item < &array[sizeof(array) / sizeof(array[0])]; item++)` – rem Sep 28 '16 at 09:55
  • 1
    @rem yes that is possible. But not portable. Typeof is nonstandard – Johannes Schaub - litb Sep 28 '16 at 17:53
  • `T*` is what exactly? – Tomáš Zato Nov 14 '16 at 17:34
  • @rem Your solution is possible without `typeof`. Just declare your variable outside of the for loop instead: `int *v; array_for(v, values) { ... }` – Charles W Aug 02 '17 at 23:01
  • The `for_each_item` macro only works like that for intrusive lists, where the next pointer is part of the elements themselves. – Andreas Haferburg Nov 19 '18 at 22:38
  • Macros are bad. I think you should use static inline functions instead of using such macros –  Sep 15 '19 at 08:31
14

As you probably already know, there's no "foreach"-style loop in C.

Although there are already tons of great macros provided here to work around this, maybe you'll find this macro useful:

// "length" is the length of the array.   
#define each(item, array, length) \
(typeof(*(array)) *p = (array), (item) = *p; p < &((array)[length]); p++, (item) = *p)

...which can be used with for (as in for each (...)).

Advantages of this approach:

  • item is declared and incremented within the for statement (just like in Python!).
  • Seems to work on any 1-dimensional array
  • All variables created in macro (p, item), aren't visible outside the scope of the loop (since they're declared in the for loop header).

Disadvantages:

  • Doesn't work for multi-dimensional arrays
  • Relies on typeof(), which is a GNU extension, not part of standard C
  • Since it declares variables in the for loop header, it only works in C11 or later.

Just to save you some time, here's how you could test it:

typedef struct {
    double x;
    double y;
} Point;

int main(void) {
    double some_nums[] = {4.2, 4.32, -9.9, 7.0};
    for each (element, some_nums, 4)
        printf("element = %lf\n", element);

    int numbers[] = {4, 2, 99, -3, 54};
    // Just demonstrating it can be used like a normal for loop
    for each (number, numbers, 5) { 
        printf("number = %d\n", number);
        if (number % 2 == 0)
                printf("%d is even.\n", number);
    }

    char* dictionary[] = {"Hello", "World"};
    for each (word, dictionary, 2)
        printf("word = '%s'\n", word);

    Point points[] = {{3.4, 4.2}, {9.9, 6.7}, {-9.8, 7.0}};
    for each (point, points, 3)
        printf("point = (%lf, %lf)\n", point.x, point.y);

    /* Neither p, element, number or word are visible outside the scope of
    their respective for loops. Try to see if these printfs work (they shouldn't): */
    //printf("*p = %s", *p);
    //printf("word = %s", word);

    return 0;
}

Seems to work on gcc and clang by default; haven't tested other compilers.

Saeed Baig
  • 1,197
  • 12
  • 13
11

Here is a full program example of a for-each macro in C99:

#include <stdio.h>

typedef struct list_node list_node;
struct list_node {
    list_node *next;
    void *data;
};

#define FOR_EACH(item, list) \
    for (list_node *(item) = (list); (item); (item) = (item)->next)

int
main(int argc, char *argv[])
{
    list_node list[] = {
        { .next = &list[1], .data = "test 1" },
        { .next = &list[2], .data = "test 2" },
        { .next = NULL,     .data = "test 3" }
    };

    FOR_EACH(item, list)
        puts((char *) item->data);

    return 0;
}
Judge Maygarden
  • 26,961
  • 9
  • 82
  • 99
  • What does the dot do in the `list[]` definition? Couldn't you simply write `next` instead of `.next`? – Rizo Jun 28 '10 at 10:25
  • 9
    @Rizo No, the dot is a part of the syntax for _C99 designated initializers_. See http://en.wikipedia.org/wiki/C_syntax#Initialization – Judge Maygarden Jun 28 '10 at 15:27
  • @Rizo: Note also that that's a really hacky way of building a linked list. It'll do for this demo but *don't* do it that way in practice! – Donal Fellows Jul 21 '10 at 15:18
  • @Donal What makes it "hacky"? – Judge Maygarden Jul 22 '10 at 13:17
  • 2
    @Judge: Well, for one thing it has “surprising” lifetime (if you're working with code which removes elements, chances are you'll crash in `free()`) and for another it has a reference to the value inside its definition. It's really an example of something that's just too damn clever; code's complex enough without purposefully adding cleverness to it. Kernighan's aphorism (http://stackoverflow.com/questions/1103299/help-me-understand-this-brian-kernighan-quote) applies! – Donal Fellows Jul 22 '10 at 23:25
9

There is no foreach in C.

You can use a for loop to loop through the data but the length needs to be know or the data needs to be terminated by a know value (eg. null).

char* nullTerm;
nullTerm = "Loop through my characters";

for(;nullTerm != NULL;nullTerm++)
{
    //nullTerm will now point to the next character.
}
Adam Peck
  • 6,930
  • 3
  • 23
  • 27
  • 1
    You should add the initialization of the nullTerm pointer to the beginning of the data set. The OP might be confused about the incomplete for loop. – cschol Dec 30 '08 at 17:54
  • Fleshed out the example a little. – Adam Peck Dec 30 '08 at 18:13
  • 1
    you are changing your original pointer, I would do something like: char* s;s="...";for(char *it=s;it!=NULL;it++){/*it point to the character*/} – hiena Aug 06 '09 at 04:32
8

While C does not have a for each construct, it has always had an idiomatic representation for one past the end of an array (&arr)[1]. This allows you to write a simple idiomatic for each loop as follows:

int arr[] = {1,2,3,4,5};
for(int *a = arr; a < (&arr)[1]; ++a)
    printf("%d\n", *a);
Steve Cox
  • 1,947
  • 13
  • 13
  • 4
    If not so sure this is well-defined. `(&arr)[1]` doesn't mean one array item past the end of the array, it means one array past the end of the array. `(&arr)[1]` is not the last item of array [0], it is the array [1], which decays into a pointer to the first element (of array [1]). I believe it would be much better, safer and idiomatic to do `const int* begin = arr; const int* end = arr + sizeof(arr)/sizeof(*arr);` and then `for(const int* a = begin; a != end; a++)`. – Lundin Oct 05 '16 at 09:22
  • 1
    @Lundin This is well defined. You're right, it's one array past the end of the array, but that array type converts to a pointer in this context (an expression), and that pointer is one past the end of the array. – Steve Cox Oct 05 '16 at 14:09
5

This is a fairly old question, but I though I should post this. It is a foreach loop for GNU C99.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define FOREACH_COMP(INDEX, ARRAY, ARRAY_TYPE, SIZE) \
  __extension__ \
  ({ \
    bool ret = 0; \
    if (__builtin_types_compatible_p (const char*, ARRAY_TYPE)) \
      ret = INDEX < strlen ((const char*)ARRAY); \
    else \
      ret = INDEX < SIZE; \
    ret; \
  })

#define FOREACH_ELEM(INDEX, ARRAY, TYPE) \
  __extension__ \
  ({ \
    TYPE *tmp_array_ = ARRAY; \
    &tmp_array_[INDEX]; \
  })

#define FOREACH(VAR, ARRAY) \
for (void *array_ = (void*)(ARRAY); array_; array_ = 0) \
for (size_t i_ = 0; i_ && array_ && FOREACH_COMP (i_, array_, \
                                    __typeof__ (ARRAY), \
                                    sizeof (ARRAY) / sizeof ((ARRAY)[0])); \
                                    i_++) \
for (bool b_ = 1; b_; (b_) ? array_ = 0 : 0, b_ = 0) \
for (VAR = FOREACH_ELEM (i_, array_, __typeof__ ((ARRAY)[0])); b_; b_ = 0)

/* example's */
int
main (int argc, char **argv)
{
  int array[10];
  /* initialize the array */
  int i = 0;
  FOREACH (int *x, array)
    {
      *x = i;
      ++i;
    }

  char *str = "hello, world!";
  FOREACH (char *c, str)
    printf ("%c\n", *c);

  return EXIT_SUCCESS;
}

This code has been tested to work with gcc, icc and clang on GNU/Linux.

Joe D
  • 2,855
  • 2
  • 31
  • 25
4

Here is what I use when I'm stuck with C. You can't use the same item name twice in the same scope, but that's not really an issue since not all of us get to use nice new compilers :(

#define FOREACH(type, item, array, size) \
    size_t X(keep), X(i); \
    type item; \
    for (X(keep) = 1, X(i) = 0 ; X(i) < (size); X(keep) = !X(keep), X(i)++) \
        for (item = (array)[X(i)]; X(keep); X(keep) = 0)

#define _foreach(item, array) FOREACH(__typeof__(array[0]), item, array, length(array))
#define foreach(item_in_array) _foreach(item_in_array)

#define in ,
#define length(array) (sizeof(array) / sizeof((array)[0]))
#define CAT(a, b) CAT_HELPER(a, b) /* Concatenate two symbols for macros! */
#define CAT_HELPER(a, b) a ## b
#define X(name) CAT(__##name, __LINE__) /* unique variable */

Usage:

int ints[] = {1, 2, 0, 3, 4};
foreach (i in ints) printf("%i", i);
/* can't use the same name in this scope anymore! */
foreach (x in ints) printf("%i", x);

EDIT: Here is an alternative for FOREACH using the c99 syntax to avoid namespace pollution:

#define FOREACH(type, item, array, size) \
    for (size_t X(keep) = 1, X(i) = 0; X(i) < (size); X(keep) = 1, X(i)++) \
    for (type item = (array)[X(i)]; X(keep); X(keep) = 0)
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Watercycle
  • 497
  • 1
  • 7
  • 12
  • Note: `VAR(i) < (size) && (item = array[VAR(i)])` would stop once the array element had a value of 0. So using this with `double Array[]` may not iterate through all elements. Seems like the loop test should be one or the other: `i – chux - Reinstate Monica Oct 16 '15 at 17:32
  • Even with pointers in my previous approach the result seems to be 'undefined behavior'. Oh well. Trust the double for loop approach! – Watercycle Oct 22 '15 at 01:54
  • This version pollutes the scope and will fail if used twice in the same scope. Also doesn't work as an un-braced block (e.g. `if ( bla ) FOREACH(....) { } else....` – M.M Nov 05 '15 at 22:15
  • 1
    1, C is the language of scope pollution, some of us are limited to older compilers. 2, Don't Repeat Yourself / be descriptive. 3, yeah, unfortunately you MUST have braces if it is going to be a conditional for loop (people usually do anyway). If you have access to a compiler that supports variable declarations in a for loop, by all means do it. – Watercycle Nov 05 '15 at 23:13
  • @Watercycle: I took the liberty to edit your answer with an alternative version of `FOREACH` that uses the c99 syntax to avoid namespace pollution. – chqrlie Aug 17 '19 at 21:14
  • DUDE! This is epic!! I can tell when someone is from the C89 gang – Valentino Zaffrani Mar 01 '22 at 05:42
3

C has 'for' and 'while' keywords. If a foreach statement in a language like C# looks like this ...

foreach (Element element in collection)
{
}

... then the equivalent of this foreach statement in C might be be like:

for (
    Element* element = GetFirstElement(&collection);
    element != 0;
    element = GetNextElement(&collection, element)
    )
{
    //TODO: do something with this element instance ...
}
ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • 2
    You should mention that your example code is not written in C syntax. – cschol Dec 30 '08 at 17:48
  • > You should mention that your example code is not written in C syntax You're right, thank you: I'll edit the post. – ChrisW Dec 30 '08 at 17:53
  • @monjardin-> sure you can just define pointer to function in the struct and there is no problem to make the call like this. – Ilya Dec 31 '08 at 07:53
1

Here's a simple one, single for loop:

#define FOREACH(type, array, size) do { \
        type it = array[0]; \
        for(int i = 0; i < size; i++, it = array[i])
#define ENDFOR  } while(0);

int array[] = { 1, 2, 3, 4, 5 };

FOREACH(int, array, 5)
{
    printf("element: %d. index: %d\n", it, i);
}
ENDFOR

Gives you access to the index should you want it (i) and the current item we're iterating over (it). Note you might have naming issues when nesting loops, you can make the item and index names be parameters to the macro.

Edit: Here's a modified version of the accepted answer foreach. Lets you specify the start index, the size so that it works on decayed arrays (pointers), no need for int* and changed count != size to i < size just in case the user accidentally modifies 'i' to be bigger than size and get stuck in an infinite loop.

#define FOREACH(item, array, start, size)\
    for(int i = start, keep = 1;\
        keep && i < size;\
        keep = !keep, i++)\
    for (item = array[i]; keep; keep = !keep)

int array[] = { 1, 2, 3, 4, 5 };
FOREACH(int x, array, 2, 5)
    printf("index: %d. element: %d\n", i, x);

Output:

index: 2. element: 3
index: 3. element: 4
index: 4. element: 5
vexe
  • 5,433
  • 12
  • 52
  • 81
1

If you're planning to work with function pointers

#define lambda(return_type, function_body)\
    ({ return_type __fn__ function_body __fn__; })

#define array_len(arr) (sizeof(arr)/sizeof(arr[0]))

#define foreachnf(type, item, arr, arr_length, func) {\
    void (*action)(type item) = func;\
    for (int i = 0; i<arr_length; i++) action(arr[i]);\
}

#define foreachf(type, item, arr, func)\
    foreachnf(type, item, arr, array_len(arr), func)

#define foreachn(type, item, arr, arr_length, body)\
    foreachnf(type, item, arr, arr_length, lambda(void, (type item) body))

#define foreach(type, item, arr, body)\
    foreachn(type, item, arr, array_len(arr), body)

Usage:

int ints[] = { 1, 2, 3, 4, 5 };
foreach(int, i, ints, {
    printf("%d\n", i);
});

char* strs[] = { "hi!", "hello!!", "hello world", "just", "testing" };
foreach(char*, s, strs, {
    printf("%s\n", s);
});

char** strsp = malloc(sizeof(char*)*2);
strsp[0] = "abcd";
strsp[1] = "efgh";
foreachn(char*, s, strsp, 2, {
    printf("%s\n", s);
});

void (*myfun)(int i) = somefunc;
foreachf(int, i, ints, myfun);

But I think this will work only on gcc (not sure).

Naheel
  • 497
  • 3
  • 13
1

C does not have an implementation of for-each. When parsing an array as a point the receiver does not know how long the array is, thus there is no way to tell when you reach the end of the array. Remember, in C int* is a point to a memory address containing an int. There is no header object containing information about how many integers that are placed in sequence. Thus, the programmer needs to keep track of this.

However, for lists, it is easy to implement something that resembles a for-each loop.

for(Node* node = head; node; node = node.next) {
   /* do your magic here */
}

To achieve something similar for arrays you can do one of two things.

  1. use the first element to store the length of the array.
  2. wrap the array in a struct which holds the length and a pointer to the array.

The following is an example of such struct:

typedef struct job_t {
   int count;
   int* arr;
} arr_t;
Jonas
  • 737
  • 1
  • 8
  • 20
1

Eric's answer doesn't work when you're using "break" or "continue".

This can be fixed by rewriting the first line:

Original line (reformatted):

for (unsigned i = 0, __a = 1; i < B.size(); i++, __a = 1)

Fixed:

for (unsigned i = 0, __a = 1; __a && i < B.size(); i++, __a = 1)

If you compare it to Johannes' loop, you'll see that he's actually doing the same, just a bit more complicated and uglier.

Community
  • 1
  • 1
0

I defined foreach using a macro and helper function. It allows for nested cycles (although limited) and the item is only defined in scope of the cycle. The only problem is that the macro contains 2 statements, so no if(...) foreach(...) printf(...);, but I wouldn't recommend doing that with any statement.

You can probably improve it with the gnu typeof macro and the #define in ,, if you want.

#define MAX_FOREACH_NESTING 16

#define foreach(type, item, set) \
    helper_foreach_next(NULL, 0, NULL, 0, 1); \
    for(type item;helper_foreach_next((char *) array, sizeof(array)/sizeof(array[0]), &item, sizeof(type), 0);)


int helper_foreach_next(char *array, size_t array_size, void *item, size_t item_size, int setup) {
    static int nesting = -1;
    static size_t indexes[MAX_FOREACH_NESTING] = { 0 };

    if(setup) {
        nesting++;
        return 0;
    }
    if (indexes[nesting] < array_size) {
        memcpy(item, array + indexes[nesting]*item_size, item_size);
        indexes[nesting]++;
        return 1;
    } else {
        indexes[nesting] = 0;
        nesting--;
        return 0;
    }
}

You can call it like this:

int array1[] = { 3, 4, 5};

foreach(int, a, array1) {
    foreach(int, b, array1) {
        printf("%d-%d\n", a, b);
    }
}
MrKew
  • 333
  • 1
  • 14
0

Here are some more foreach macros:

They are fully standard-compliant but require C99.

Standard

  • type cannot be const-qualified
  • Mangles a pointer to the current element: you can change __p_##varName to a friendlier name if necessary.
#include <stdio.h>

#define foreach(type, varName, array, count) for (   \
    type *__p_##varName = array, varName = array[0]; \
    __p_##varName != array + count;                  \
    varName = *(++__p_##varName))

int main()
{
    int arr[] = { 1,2,3,4,5 };
    
    foreach(int, myInt, arr, 5)
    {
        printf("%d\n", myInt);
    }
    
    return 0;
}

Pointer

  • type can be const-qualified
  • varName will be of type*
#include <stdio.h>

#define foreach(type, varName, array, count) for ( \
    type *varName = array;                         \
    varName != array + count;                      \
    ++varName)

int main()
{
    int arr[] = { 1,2,3,4,5 };
    
    foreach(int const, myInt, arr, 5)
    {
        printf("%d\n", *myInt);
    }
    
    return 0;
}

Body

  • type can be const-qualified
  • Requires loop body to be passed as an argument
  • Mangles a pointer to the current element: you can change __p_##varName to a friendlier name if necessary.
#include <stdio.h>

#define foreach(type, varName, array, count, body) for ( \
    type *__p_##varName = array;                         \
    __p_##varName != array + count;                      \
    ++__p_##varName)                                     \
    { type varName = *__p_##varName; { body } }

int main()
{
    int arr[] = { 1,2,3,4,5 };
    
    foreach(int const, myInt, arr, 5,
    {
        printf("%d\n", myInt);
    })

    // Also supports single-statement style:
    foreach(int const, myInt, arr, 5,
        printf("%d\n", myInt);)
    
    return 0;
}

Please be careful though: defining custom control structures with macros could hurt code readability.

Scover
  • 93
  • 9