this is relatively simple to do once you agree to hard-code the length of the string. The hard requirements is that you have to hard-code the string length, because it is not possible to get it in preprocessor. Having the string length, you call the proper macro and expand the chain however you want.
I would first start with a boilerplate FOREACH macro that calls a function with an index and two arguments. As we know the length at preprocessor time, we can call the proper overload FOREACH_##strlen statically.
For the requirement of hardcoding string length, I would throw in a static assertion, making sure you have to change it when you change the string.
#define FOREACH_0(f, a, b)
#define FOREACH_1(f, a, b) f(0, a, b),
#define FOREACH_2(f, a, b) FOREACH_1(f, a, b) f(1, a, b),
#define FOREACH_3(f, a, b) FOREACH_2(f, a, b) f(2, a, b),
#define FOREACH_4(f, a, b) FOREACH_3(f, a, b) f(3, a, b),
#define FOREACH_5(f, a, b) FOREACH_4(f, a, b) f(4, a, b),
#define FOREACH_6(f, a, b) FOREACH_5(f, a, b) f(5, a, b),
#define FOREACH_7(f, a, b) FOREACH_6(f, a, b) f(6, a, b),
#define FOREACH_8(f, a, b) FOREACH_7(f, a, b) f(7, a, b),
#define FOREACH_9(f, a, b) FOREACH_8(f, a, b) f(8, a, b),
#define FOREACH_10(f, a, b) FOREACH_9(f, a, b) f(9, a, b),
#define FOREACH_N(_10,_9,_8,_7,_6,_5,_4,_3,_2,_1,...) FOREACH_##N
#define FOREACH(f, a, b, ...) FOREACH_N(__VA_ARGS__,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1)(f, a, b)
#define STATIC_ASSERT(...) \
sizeof(struct{_Static_assert(__VA_ARGS__); int dummy;})
#define MODIFY_CB(idx, str, num) str[idx]^num
#define MODIFY(str, strlen, num) { \
FOREACH_##strlen(MODIFY_CB, str, num) \
0 * STATIC_ASSERT(sizeof(str) == strlen + 1) \
}
char text[] = MODIFY("test text", 9, 10);
Expanding the code to handle more cases is trivial - it's just adding more FOREACH_*.
Notes: identifiers starting with _ and upper case letter are reserved, you are not allowed to define _MODIFY, do not use such identifiers.
char text[] = "test text";isn't compiled with the character codes? The't'is just a shortcut way of writing116anyway, but more portable.