2

here is my code, I find "each" macro only iterate first element and output "s1", how to make it iterate all elements?

#include "stdio.h"

#define each(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)

char *join(char const *ss[]) {
    char *r = "";
    each(char *s, ss) {
            puts(s);
        }
    return (r);
}

int main(int argc, char **argv) {
    char const *ss[] = {"s1", "s2"};
    join(ss);
};
nwaicaethi
  • 155
  • 3
  • 9
  • 1
    Please don't write macros like these; don't try to change the C language. You can assume that every other C programmer knows C. You can't assume that they know or care to learn about your home-brewed, secret macro language. This is very bad programming practice. – Lundin Oct 28 '15 at 09:20
  • It doesn't look like a good idea to put a double-nested loop in a macro called `each`. That logic is more complex than you can consider "boilerplate". Also, you should user UPPERCASE macro names when you're doing stuff that isn't function-like. (e.g. a `max` macro might be ok if it uses GNU C features to avoid evaluating its args multiple times.) – Peter Cordes Oct 28 '15 at 09:20

3 Answers3

1

If you call each from main, i.e. place where ss is defined, your program works as expected:

int main(int argc, char **argv) {
    char const *ss[] = {"s1", "s2"};

    each(char *s, ss) {
        puts(s);
    }
};

It works because each has access to ss declaration, so that sizeof a / sizeof *a is equal to number of elements in array.

The problem is that if you pass ss array to another function (e.g. join), it decays to pointer. As ss in join is a pointer, sizeof array no longer refers to size of array, and expresssion sizeof a / sizeof *a yields sizeof(char**)/sizeof(char*) which is 1 on your platform.

See also

What is array decaying?

Community
  • 1
  • 1
el.pescado
  • 17,764
  • 2
  • 43
  • 82
0

Considering the below terminology

for(initialization statement; condition; update statement) {
       code/s to be executed; 
}

Your condition has a statement keep && count != size; which is checking for the keep value to be non-zero.

And in the update statement you are doing keep = !keep which is making keep value to 0.

Hence your loop is exiting in single iteration. Modify your condition accordingly to loop multiple times.

Raghu Srikanth Reddy
  • 2,629
  • 33
  • 27
  • 39
0

Here macro not creating any problem macro just place code whenever you used,

you need to check your for loops ,

size = sizeof(array) / sizeof *(array); 

In above statement sizeof(array) and sizeof *(array) both are giving sizeof pointers. So the size is always 1 .

Next is inside or 2nd for loop iterate only once because you did keep = !keep which change the keep = 0 ;

So now it's completed first iteration, it going to update keep = !keep, count++) , After that it check the condition keep && count != size in this

keep = 1;

count= 1; and

size = 1;

so it is terminating the loop , so check your for loop condition part.

if you have intention to just iterate for all items in char array then there are number of solution do that , I just listing one of them change in your code

In macro

for (int keep = 1, count = 0, size = sizeof(ss) / sizeof *(ss); ss[count] != "\0"; keep = !keep, count++) \

In main function

char const *ss[] = { "s1", "s2","\0" };

Now you will get as expected output.

Mohan
  • 1,781
  • 17
  • 28