A macro isn't a function, it's inline assembly. You put this into the compuler...
And your compiler has to read the code twice. First, it goes through and takes care of all the macros and definitions, changing the former code into this...
putchar(TOUPPER (s[++i]); /* call of macro */
Broke the macro onto several lines for viewability. Hope that doesn't confuse...
('a' <= (s[++i]) && (s[++i]) <= 'z' ?
(s[++i]) - 'a' + 'A' : (s[++i]))
); /* call of macro */
Now, that beast of a line that the preprocessor threw into our putchar is what actually gets compiled, so let's just go through it....
1. 'a' <= (s[++i]) // ++i, then 'a' <= s TRUE
2. (s[++i]) <= 'z' // ++ i, then s <= 'z' TRUE
3. s[++i] - 'a' + 'A' // ++i, then return s - 'a' + 'A', which is U