If you look into the CImg header, you'll see that that code is, in fact, a macro that thunks down into:
#define cimg_forXY(img,x,y) cimg_forY(img,y) cimg_forX(img,x)
#define cimg_forX(img,x) for (int x=0; x<(int)((img).width); ++x)
#define cimg_forY(img,y) for (int y=0; y<(int)((img).height); ++y)
#define cimg_forZ(img,z) for (int z=0; z<(int)((img).depth); ++z)
#define cimg_forXYZ(img,x,y,z) cimg_forZ(img,z) cimg_forXY(img,x,y)
Which means that you will have the following loops:
for (int z=0; z<(int)((img).depth); ++z)
for (int y=0; y<(int)((img).height); ++y)
for (int x=0; x<(int)((img).width); ++x) {
}
So, now, what you probably want to do is reference either the x, y, and z coordinates, or better, the pointer into the data as you step through, like
cimg_library::CImg<float> image;
//assign, etc
float* ptr = image->ptr();
cimg_forXYZ(S, x, y, z){
*ptr = *ptr + 10;
++ptr;
}
I encourage you to read the CImg header; it's quite elegant. You'll get a lot of functionality 'for free'.