Does C have a “foreach” loop construct?
Almost all languages have a foreach
loop or something similar. Does C have one? Can you post some example code?
c foreach
add a comment |
Almost all languages have a foreach
loop or something similar. Does C have one? Can you post some example code?
c foreach
"foreach
" of what?
– alk
Mar 6 '16 at 11:13
How hard would it have been to try writing aforeach
loop in a C program?
– MD XF
Oct 17 '16 at 0:04
add a comment |
Almost all languages have a foreach
loop or something similar. Does C have one? Can you post some example code?
c foreach
Almost all languages have a foreach
loop or something similar. Does C have one? Can you post some example code?
c foreach
c foreach
edited May 19 '17 at 1:46
MD XF
4,09652854
4,09652854
asked Dec 30 '08 at 17:39
QuestionQuestion
532196
532196
"foreach
" of what?
– alk
Mar 6 '16 at 11:13
How hard would it have been to try writing aforeach
loop in a C program?
– MD XF
Oct 17 '16 at 0:04
add a comment |
"foreach
" of what?
– alk
Mar 6 '16 at 11:13
How hard would it have been to try writing aforeach
loop in a C program?
– MD XF
Oct 17 '16 at 0:04
"
foreach
" of what?– alk
Mar 6 '16 at 11:13
"
foreach
" of what?– alk
Mar 6 '16 at 11:13
How hard would it have been to try writing a
foreach
loop in a C program?– MD XF
Oct 17 '16 at 0:04
How hard would it have been to try writing a
foreach
loop in a C program?– MD XF
Oct 17 '16 at 0:04
add a comment |
13 Answers
13
active
oldest
votes
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: %dn", *v);
}
Edit: In case you are also interested in C++ solutions, C++ has a native for-each syntax called "range based for"
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 6 '09 at 4:46
3
@eSKay yes considerif(...) foreach(int *v, values) ...
. If they are outside the loop it expands toif(...) int count = 0 ...; for(...) ...;
and will break.
– Johannes Schaub - litb
May 9 '10 at 11:37
1
@fred to make "break" work
– Johannes Schaub - litb
Feb 15 '12 at 10:34
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
|
show 13 more comments
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;
}
What does the dot do in thelist
definition? Couldn't you simply writenext
instead of.next
?
– Rizo
Jun 28 '10 at 10:25
7
@Rizo No, the dot is a part of the syntax for C99 designated initializers. See 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
1
@Judge: Well, for one thing it has “surprising” lifetime (if you're working with code which removes elements, chances are you'll crash infree()
) 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 (stackoverflow.com/questions/1103299/…) applies!
– Donal Fellows
Jul 22 '10 at 23:25
add a comment |
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.
}
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
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 6 '09 at 4:32
add a comment |
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 ("%cn", *c);
return EXIT_SUCCESS;
}
This code has been tested to work with gcc, icc and clang on GNU/Linux.
add a comment |
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("%dn", *a);
3
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 doconst int* begin = arr; const int* end = arr + sizeof(arr)/sizeof(*arr);
and thenfor(const int* a = begin; a != end; a++)
.
– Lundin
Oct 5 '16 at 9: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 5 '16 at 14:09
add a comment |
As u probably already know, there's no "foreach" style loop in C.
Altho 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 gcc 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 _point {
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 = %lfn", 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 = %dn", 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; not sure about other compilers.
add a comment |
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 ...
}
1
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 7:53
add a comment |
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.
add a comment |
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: %dn", 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: %dn", i, x);
Output:
index: 2. element: 3
index: 3. element: 4
index: 4. element: 5
add a comment |
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.
- use the first element to store the length of the array.
- 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;
add a comment |
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);
Note:VAR(i) < (size) && (item = array[VAR(i)])
would stop once the array element had a value of 0. So using this withdouble Array
may not iterate through all elements. Seems like the loop test should be one or the other:i<n
orA[i]
. Maybe add sample use cases for clarity.
– chux
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 1: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 5 '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 5 '15 at 23:13
add a comment |
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("%dn", i);
});
char* strs = { "hi!", "hello!!", "hello world", "just", "testing" };
foreach(char*, s, strs, {
printf("%sn", s);
});
char** strsp = malloc(sizeof(char*)*2);
strsp[0] = "abcd";
strsp[1] = "efgh";
foreachn(char*, s, strsp, 2, {
printf("%sn", s);
});
void (*myfun)(int i) = somefunc;
foreachf(int, i, ints, myfun);
But I think this will work only on gcc (not sure).
add a comment |
Thanks to accepted answer I was able to fix my C++ macro. It's not clean, but it supports nesting, break and continue, and for a list<t>
it allows to iterate over the t&
instead of list<t>::elem*
, so you don't have to dereference.
template <typename t> struct list { // =list=
struct elem {
t Data;
elem* Next;
};
elem* Head;
elem* Tail;
};
#define for_list3(TYPE, NAME, NAME2, LIST)
bool _##NAME##NAME2 = true;
for (list<TYPE>::elem* NAME##_E = LIST.Head;
NAME##_E && _##NAME##NAME2;
_##NAME##NAME2 = !_##NAME##NAME2, NAME##_E = NAME##_E->Next)
for (auto& NAME = NAME##_E->Data; _##NAME##NAME2; _##NAME##NAME2=false)
#define for_list2(TYPE, NAME, NAME2, LIST) for_list3(TYPE, NAME, NAME2, LIST)
#define for_list(TYPE, NAME, LIST) for_list2(TYPE, NAME, __COUNTER__, LIST)
void example() {
list<string> Words;
for_list(string, Word, Words) {
print(Word);
}
}
With the for_each_item
macro from the accepted answer, you'd have to do this:
void example2() {
list<string> Words;
for_each_item(string, Elem, Words) {
string& Word = Elem->Data;
print(Word);
}
}
If you want to rewrite it into a clean version, feel free to edit.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f400951%2fdoes-c-have-a-foreach-loop-construct%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
13 Answers
13
active
oldest
votes
13 Answers
13
active
oldest
votes
active
oldest
votes
active
oldest
votes
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: %dn", *v);
}
Edit: In case you are also interested in C++ solutions, C++ has a native for-each syntax called "range based for"
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 6 '09 at 4:46
3
@eSKay yes considerif(...) foreach(int *v, values) ...
. If they are outside the loop it expands toif(...) int count = 0 ...; for(...) ...;
and will break.
– Johannes Schaub - litb
May 9 '10 at 11:37
1
@fred to make "break" work
– Johannes Schaub - litb
Feb 15 '12 at 10:34
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
|
show 13 more comments
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: %dn", *v);
}
Edit: In case you are also interested in C++ solutions, C++ has a native for-each syntax called "range based for"
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 6 '09 at 4:46
3
@eSKay yes considerif(...) foreach(int *v, values) ...
. If they are outside the loop it expands toif(...) int count = 0 ...; for(...) ...;
and will break.
– Johannes Schaub - litb
May 9 '10 at 11:37
1
@fred to make "break" work
– Johannes Schaub - litb
Feb 15 '12 at 10:34
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
|
show 13 more comments
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: %dn", *v);
}
Edit: In case you are also interested in C++ solutions, C++ has a native for-each syntax called "range based for"
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: %dn", *v);
}
Edit: In case you are also interested in C++ solutions, C++ has a native for-each syntax called "range based for"
edited Sep 22 '15 at 16:39
answered Dec 30 '08 at 17:51


Johannes Schaub - litbJohannes Schaub - litb
405k1007731107
405k1007731107
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 6 '09 at 4:46
3
@eSKay yes considerif(...) foreach(int *v, values) ...
. If they are outside the loop it expands toif(...) int count = 0 ...; for(...) ...;
and will break.
– Johannes Schaub - litb
May 9 '10 at 11:37
1
@fred to make "break" work
– Johannes Schaub - litb
Feb 15 '12 at 10:34
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
|
show 13 more comments
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 6 '09 at 4:46
3
@eSKay yes considerif(...) foreach(int *v, values) ...
. If they are outside the loop it expands toif(...) int count = 0 ...; for(...) ...;
and will break.
– Johannes Schaub - litb
May 9 '10 at 11:37
1
@fred to make "break" work
– Johannes Schaub - litb
Feb 15 '12 at 10:34
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
1
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 6 '09 at 4:46
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 6 '09 at 4:46
3
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 9 '10 at 11:37
@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 9 '10 at 11:37
1
1
@fred to make "break" work
– Johannes Schaub - litb
Feb 15 '12 at 10:34
@fred to make "break" work
– Johannes Schaub - litb
Feb 15 '12 at 10:34
1
1
@rem it does not break the outer loop if you use "break"
– Johannes Schaub - litb
Sep 26 '16 at 11:05
@rem it does not break the outer loop if you use "break"
– Johannes Schaub - litb
Sep 26 '16 at 11:05
1
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
@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
|
show 13 more comments
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;
}
What does the dot do in thelist
definition? Couldn't you simply writenext
instead of.next
?
– Rizo
Jun 28 '10 at 10:25
7
@Rizo No, the dot is a part of the syntax for C99 designated initializers. See 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
1
@Judge: Well, for one thing it has “surprising” lifetime (if you're working with code which removes elements, chances are you'll crash infree()
) 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 (stackoverflow.com/questions/1103299/…) applies!
– Donal Fellows
Jul 22 '10 at 23:25
add a comment |
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;
}
What does the dot do in thelist
definition? Couldn't you simply writenext
instead of.next
?
– Rizo
Jun 28 '10 at 10:25
7
@Rizo No, the dot is a part of the syntax for C99 designated initializers. See 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
1
@Judge: Well, for one thing it has “surprising” lifetime (if you're working with code which removes elements, chances are you'll crash infree()
) 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 (stackoverflow.com/questions/1103299/…) applies!
– Donal Fellows
Jul 22 '10 at 23:25
add a comment |
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;
}
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;
}
answered Dec 30 '08 at 18:13
Judge MaygardenJudge Maygarden
21.4k76591
21.4k76591
What does the dot do in thelist
definition? Couldn't you simply writenext
instead of.next
?
– Rizo
Jun 28 '10 at 10:25
7
@Rizo No, the dot is a part of the syntax for C99 designated initializers. See 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
1
@Judge: Well, for one thing it has “surprising” lifetime (if you're working with code which removes elements, chances are you'll crash infree()
) 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 (stackoverflow.com/questions/1103299/…) applies!
– Donal Fellows
Jul 22 '10 at 23:25
add a comment |
What does the dot do in thelist
definition? Couldn't you simply writenext
instead of.next
?
– Rizo
Jun 28 '10 at 10:25
7
@Rizo No, the dot is a part of the syntax for C99 designated initializers. See 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
1
@Judge: Well, for one thing it has “surprising” lifetime (if you're working with code which removes elements, chances are you'll crash infree()
) 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 (stackoverflow.com/questions/1103299/…) applies!
– Donal Fellows
Jul 22 '10 at 23:25
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
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
7
7
@Rizo No, the dot is a part of the syntax for C99 designated initializers. See en.wikipedia.org/wiki/C_syntax#Initialization
– Judge Maygarden
Jun 28 '10 at 15:27
@Rizo No, the dot is a part of the syntax for C99 designated initializers. See 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
@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
@Donal What makes it "hacky"?
– Judge Maygarden
Jul 22 '10 at 13:17
1
1
@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 (stackoverflow.com/questions/1103299/…) applies!– Donal Fellows
Jul 22 '10 at 23:25
@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 (stackoverflow.com/questions/1103299/…) applies!– Donal Fellows
Jul 22 '10 at 23:25
add a comment |
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.
}
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
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 6 '09 at 4:32
add a comment |
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.
}
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
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 6 '09 at 4:32
add a comment |
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.
}
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.
}
edited Dec 30 '08 at 18:06
answered Dec 30 '08 at 17:43
Adam PeckAdam Peck
4,28631827
4,28631827
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
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 6 '09 at 4:32
add a comment |
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
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 6 '09 at 4:32
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
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
Fleshed out the example a little.
– Adam Peck
Dec 30 '08 at 18:13
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 6 '09 at 4:32
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 6 '09 at 4:32
add a comment |
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 ("%cn", *c);
return EXIT_SUCCESS;
}
This code has been tested to work with gcc, icc and clang on GNU/Linux.
add a comment |
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 ("%cn", *c);
return EXIT_SUCCESS;
}
This code has been tested to work with gcc, icc and clang on GNU/Linux.
add a comment |
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 ("%cn", *c);
return EXIT_SUCCESS;
}
This code has been tested to work with gcc, icc and clang on GNU/Linux.
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 ("%cn", *c);
return EXIT_SUCCESS;
}
This code has been tested to work with gcc, icc and clang on GNU/Linux.
answered Jul 21 '10 at 15:12
Joe DJoe D
2,37812425
2,37812425
add a comment |
add a comment |
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("%dn", *a);
3
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 doconst int* begin = arr; const int* end = arr + sizeof(arr)/sizeof(*arr);
and thenfor(const int* a = begin; a != end; a++)
.
– Lundin
Oct 5 '16 at 9: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 5 '16 at 14:09
add a comment |
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("%dn", *a);
3
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 doconst int* begin = arr; const int* end = arr + sizeof(arr)/sizeof(*arr);
and thenfor(const int* a = begin; a != end; a++)
.
– Lundin
Oct 5 '16 at 9: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 5 '16 at 14:09
add a comment |
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("%dn", *a);
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("%dn", *a);
answered Jun 2 '16 at 14:32
Steve CoxSteve Cox
1,329811
1,329811
3
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 doconst int* begin = arr; const int* end = arr + sizeof(arr)/sizeof(*arr);
and thenfor(const int* a = begin; a != end; a++)
.
– Lundin
Oct 5 '16 at 9: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 5 '16 at 14:09
add a comment |
3
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 doconst int* begin = arr; const int* end = arr + sizeof(arr)/sizeof(*arr);
and thenfor(const int* a = begin; a != end; a++)
.
– Lundin
Oct 5 '16 at 9: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 5 '16 at 14:09
3
3
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 5 '16 at 9:22
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 5 '16 at 9:22
1
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 5 '16 at 14:09
@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 5 '16 at 14:09
add a comment |
As u probably already know, there's no "foreach" style loop in C.
Altho 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 gcc 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 _point {
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 = %lfn", 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 = %dn", 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; not sure about other compilers.
add a comment |
As u probably already know, there's no "foreach" style loop in C.
Altho 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 gcc 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 _point {
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 = %lfn", 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 = %dn", 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; not sure about other compilers.
add a comment |
As u probably already know, there's no "foreach" style loop in C.
Altho 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 gcc 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 _point {
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 = %lfn", 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 = %dn", 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; not sure about other compilers.
As u probably already know, there's no "foreach" style loop in C.
Altho 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 gcc 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 _point {
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 = %lfn", 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 = %dn", 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; not sure about other compilers.
edited Jul 7 '18 at 23:43
answered Nov 6 '17 at 9:47
Saeed BaigSaeed Baig
35926
35926
add a comment |
add a comment |
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 ...
}
1
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 7:53
add a comment |
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 ...
}
1
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 7:53
add a comment |
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 ...
}
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 ...
}
edited Dec 30 '08 at 17:55
answered Dec 30 '08 at 17:45
ChrisWChrisW
45.5k983185
45.5k983185
1
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 7:53
add a comment |
1
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 7:53
1
1
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.
– 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
> 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 7: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 7:53
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
edited May 23 '17 at 12:03
Community♦
11
11
answered Jul 14 '11 at 22:04
Michael BlurbMichael Blurb
283
283
add a comment |
add a comment |
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: %dn", 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: %dn", i, x);
Output:
index: 2. element: 3
index: 3. element: 4
index: 4. element: 5
add a comment |
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: %dn", 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: %dn", i, x);
Output:
index: 2. element: 3
index: 3. element: 4
index: 4. element: 5
add a comment |
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: %dn", 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: %dn", i, x);
Output:
index: 2. element: 3
index: 3. element: 4
index: 4. element: 5
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: %dn", 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: %dn", i, x);
Output:
index: 2. element: 3
index: 3. element: 4
index: 4. element: 5
edited Aug 29 '15 at 13:12
answered Aug 27 '15 at 17:45


vexevexe
2,17273360
2,17273360
add a comment |
add a comment |
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.
- use the first element to store the length of the array.
- 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;
add a comment |
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.
- use the first element to store the length of the array.
- 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;
add a comment |
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.
- use the first element to store the length of the array.
- 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;
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.
- use the first element to store the length of the array.
- 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;
answered Mar 14 '18 at 23:12
JonasJonas
355416
355416
add a comment |
add a comment |
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);
Note:VAR(i) < (size) && (item = array[VAR(i)])
would stop once the array element had a value of 0. So using this withdouble Array
may not iterate through all elements. Seems like the loop test should be one or the other:i<n
orA[i]
. Maybe add sample use cases for clarity.
– chux
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 1: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 5 '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 5 '15 at 23:13
add a comment |
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);
Note:VAR(i) < (size) && (item = array[VAR(i)])
would stop once the array element had a value of 0. So using this withdouble Array
may not iterate through all elements. Seems like the loop test should be one or the other:i<n
orA[i]
. Maybe add sample use cases for clarity.
– chux
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 1: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 5 '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 5 '15 at 23:13
add a comment |
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);
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);
edited Nov 5 '15 at 23:08
answered Sep 29 '15 at 7:34


WatercycleWatercycle
43137
43137
Note:VAR(i) < (size) && (item = array[VAR(i)])
would stop once the array element had a value of 0. So using this withdouble Array
may not iterate through all elements. Seems like the loop test should be one or the other:i<n
orA[i]
. Maybe add sample use cases for clarity.
– chux
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 1: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 5 '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 5 '15 at 23:13
add a comment |
Note:VAR(i) < (size) && (item = array[VAR(i)])
would stop once the array element had a value of 0. So using this withdouble Array
may not iterate through all elements. Seems like the loop test should be one or the other:i<n
orA[i]
. Maybe add sample use cases for clarity.
– chux
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 1: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 5 '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 5 '15 at 23:13
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<n
or A[i]
. Maybe add sample use cases for clarity.– chux
Oct 16 '15 at 17:32
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<n
or A[i]
. Maybe add sample use cases for clarity.– chux
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 1:54
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 1: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 5 '15 at 22:15
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 5 '15 at 22:15
1
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 5 '15 at 23:13
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 5 '15 at 23:13
add a comment |
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("%dn", i);
});
char* strs = { "hi!", "hello!!", "hello world", "just", "testing" };
foreach(char*, s, strs, {
printf("%sn", s);
});
char** strsp = malloc(sizeof(char*)*2);
strsp[0] = "abcd";
strsp[1] = "efgh";
foreachn(char*, s, strsp, 2, {
printf("%sn", s);
});
void (*myfun)(int i) = somefunc;
foreachf(int, i, ints, myfun);
But I think this will work only on gcc (not sure).
add a comment |
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("%dn", i);
});
char* strs = { "hi!", "hello!!", "hello world", "just", "testing" };
foreach(char*, s, strs, {
printf("%sn", s);
});
char** strsp = malloc(sizeof(char*)*2);
strsp[0] = "abcd";
strsp[1] = "efgh";
foreachn(char*, s, strsp, 2, {
printf("%sn", s);
});
void (*myfun)(int i) = somefunc;
foreachf(int, i, ints, myfun);
But I think this will work only on gcc (not sure).
add a comment |
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("%dn", i);
});
char* strs = { "hi!", "hello!!", "hello world", "just", "testing" };
foreach(char*, s, strs, {
printf("%sn", s);
});
char** strsp = malloc(sizeof(char*)*2);
strsp[0] = "abcd";
strsp[1] = "efgh";
foreachn(char*, s, strsp, 2, {
printf("%sn", s);
});
void (*myfun)(int i) = somefunc;
foreachf(int, i, ints, myfun);
But I think this will work only on gcc (not sure).
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("%dn", i);
});
char* strs = { "hi!", "hello!!", "hello world", "just", "testing" };
foreach(char*, s, strs, {
printf("%sn", s);
});
char** strsp = malloc(sizeof(char*)*2);
strsp[0] = "abcd";
strsp[1] = "efgh";
foreachn(char*, s, strsp, 2, {
printf("%sn", s);
});
void (*myfun)(int i) = somefunc;
foreachf(int, i, ints, myfun);
But I think this will work only on gcc (not sure).
answered May 15 '17 at 20:01
NaheelNaheel
362210
362210
add a comment |
add a comment |
Thanks to accepted answer I was able to fix my C++ macro. It's not clean, but it supports nesting, break and continue, and for a list<t>
it allows to iterate over the t&
instead of list<t>::elem*
, so you don't have to dereference.
template <typename t> struct list { // =list=
struct elem {
t Data;
elem* Next;
};
elem* Head;
elem* Tail;
};
#define for_list3(TYPE, NAME, NAME2, LIST)
bool _##NAME##NAME2 = true;
for (list<TYPE>::elem* NAME##_E = LIST.Head;
NAME##_E && _##NAME##NAME2;
_##NAME##NAME2 = !_##NAME##NAME2, NAME##_E = NAME##_E->Next)
for (auto& NAME = NAME##_E->Data; _##NAME##NAME2; _##NAME##NAME2=false)
#define for_list2(TYPE, NAME, NAME2, LIST) for_list3(TYPE, NAME, NAME2, LIST)
#define for_list(TYPE, NAME, LIST) for_list2(TYPE, NAME, __COUNTER__, LIST)
void example() {
list<string> Words;
for_list(string, Word, Words) {
print(Word);
}
}
With the for_each_item
macro from the accepted answer, you'd have to do this:
void example2() {
list<string> Words;
for_each_item(string, Elem, Words) {
string& Word = Elem->Data;
print(Word);
}
}
If you want to rewrite it into a clean version, feel free to edit.
add a comment |
Thanks to accepted answer I was able to fix my C++ macro. It's not clean, but it supports nesting, break and continue, and for a list<t>
it allows to iterate over the t&
instead of list<t>::elem*
, so you don't have to dereference.
template <typename t> struct list { // =list=
struct elem {
t Data;
elem* Next;
};
elem* Head;
elem* Tail;
};
#define for_list3(TYPE, NAME, NAME2, LIST)
bool _##NAME##NAME2 = true;
for (list<TYPE>::elem* NAME##_E = LIST.Head;
NAME##_E && _##NAME##NAME2;
_##NAME##NAME2 = !_##NAME##NAME2, NAME##_E = NAME##_E->Next)
for (auto& NAME = NAME##_E->Data; _##NAME##NAME2; _##NAME##NAME2=false)
#define for_list2(TYPE, NAME, NAME2, LIST) for_list3(TYPE, NAME, NAME2, LIST)
#define for_list(TYPE, NAME, LIST) for_list2(TYPE, NAME, __COUNTER__, LIST)
void example() {
list<string> Words;
for_list(string, Word, Words) {
print(Word);
}
}
With the for_each_item
macro from the accepted answer, you'd have to do this:
void example2() {
list<string> Words;
for_each_item(string, Elem, Words) {
string& Word = Elem->Data;
print(Word);
}
}
If you want to rewrite it into a clean version, feel free to edit.
add a comment |
Thanks to accepted answer I was able to fix my C++ macro. It's not clean, but it supports nesting, break and continue, and for a list<t>
it allows to iterate over the t&
instead of list<t>::elem*
, so you don't have to dereference.
template <typename t> struct list { // =list=
struct elem {
t Data;
elem* Next;
};
elem* Head;
elem* Tail;
};
#define for_list3(TYPE, NAME, NAME2, LIST)
bool _##NAME##NAME2 = true;
for (list<TYPE>::elem* NAME##_E = LIST.Head;
NAME##_E && _##NAME##NAME2;
_##NAME##NAME2 = !_##NAME##NAME2, NAME##_E = NAME##_E->Next)
for (auto& NAME = NAME##_E->Data; _##NAME##NAME2; _##NAME##NAME2=false)
#define for_list2(TYPE, NAME, NAME2, LIST) for_list3(TYPE, NAME, NAME2, LIST)
#define for_list(TYPE, NAME, LIST) for_list2(TYPE, NAME, __COUNTER__, LIST)
void example() {
list<string> Words;
for_list(string, Word, Words) {
print(Word);
}
}
With the for_each_item
macro from the accepted answer, you'd have to do this:
void example2() {
list<string> Words;
for_each_item(string, Elem, Words) {
string& Word = Elem->Data;
print(Word);
}
}
If you want to rewrite it into a clean version, feel free to edit.
Thanks to accepted answer I was able to fix my C++ macro. It's not clean, but it supports nesting, break and continue, and for a list<t>
it allows to iterate over the t&
instead of list<t>::elem*
, so you don't have to dereference.
template <typename t> struct list { // =list=
struct elem {
t Data;
elem* Next;
};
elem* Head;
elem* Tail;
};
#define for_list3(TYPE, NAME, NAME2, LIST)
bool _##NAME##NAME2 = true;
for (list<TYPE>::elem* NAME##_E = LIST.Head;
NAME##_E && _##NAME##NAME2;
_##NAME##NAME2 = !_##NAME##NAME2, NAME##_E = NAME##_E->Next)
for (auto& NAME = NAME##_E->Data; _##NAME##NAME2; _##NAME##NAME2=false)
#define for_list2(TYPE, NAME, NAME2, LIST) for_list3(TYPE, NAME, NAME2, LIST)
#define for_list(TYPE, NAME, LIST) for_list2(TYPE, NAME, __COUNTER__, LIST)
void example() {
list<string> Words;
for_list(string, Word, Words) {
print(Word);
}
}
With the for_each_item
macro from the accepted answer, you'd have to do this:
void example2() {
list<string> Words;
for_each_item(string, Elem, Words) {
string& Word = Elem->Data;
print(Word);
}
}
If you want to rewrite it into a clean version, feel free to edit.
edited Nov 19 '18 at 22:40
answered Nov 19 '18 at 22:31
Andreas HaferburgAndreas Haferburg
3,33411947
3,33411947
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f400951%2fdoes-c-have-a-foreach-loop-construct%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
"
foreach
" of what?– alk
Mar 6 '16 at 11:13
How hard would it have been to try writing a
foreach
loop in a C program?– MD XF
Oct 17 '16 at 0:04