1

Lets say I have this macro

#define last(x) printf("%c", #x[last]);

I want it to print the last char of x, where x is not a string.

How can I get the last char of x ? Is there a short way to do it?

int main(){
    last(abc);
}

output: c
Daniel
  • 7,357
  • 7
  • 32
  • 84

2 Answers2

4

Easy to do when we remember that string literals are just arrays we can index into:

#define last(x) std::printf("%c", #x[sizeof(#x) - 2]);

Live

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • This will only work if x is a string literal. If it is an array, it will not work. Then you will need `strlen` – Rishikesh Raje Jul 16 '16 at 22:49
  • @RishikeshRaje `#x` is always a string literal, the preprocessor does not care about types. – Baum mit Augen Jul 16 '16 at 22:50
  • if the string is defined like `char a[50]` and the input is taken from `scanf` then the last character of the string is not `a[48]` but is dependent on what the input is. That we can only get from `strlen(a) -1` – Rishikesh Raje Jul 16 '16 at 22:58
  • @RishikeshRaje The string is defined by `#x`. That is a string literal. Always. Because that's what the `#` operator does. – Baum mit Augen Jul 16 '16 at 23:00
  • supposing the parameter given to last is in form NNN...NNC, where N is a number and C is a char, is there a smaller way to get the last char? I just want the last char, not its index (although index is useful too). example: last(123a) = a – Daniel Jul 16 '16 at 23:01
  • 1
    @Daniel I don't understand. The solution above already does what your example requires. What do you mean with "a smaller way"? A shorter macro? – Baum mit Augen Jul 16 '16 at 23:04
  • @Daniel [Here, now it's shorter](http://coliru.stacked-crooked.com/a/cc04385f5996fc37). ;) Joke aside, I don't see any benefit in making the macro shorter, and it would most likely hurt clarity and readability. – Baum mit Augen Jul 16 '16 at 23:14
  • ignore readability, its just for me. I thought of that too but I was thinking about ## or something like q(abc) ab##c, dont know :) I'm probably wrong for trying to use ## to split instead of concat. Anyway, if its the smaller it can get, no problems – Daniel Jul 16 '16 at 23:21
  • @BaummitAugen I was thinking of a different use case than what OP requires. Your solution will work for what OP wants. – Rishikesh Raje Jul 17 '16 at 00:26
3

You want

#define last(x) printf("%c", #x[sizeof(#x)-2]);

Demo: https://ideone.com/rp0w8k

(sizeof gives you the number of bytes in the string literal formed by stringizing the macro argument, back one to get the terminating zero, back another one to get to the last character.)

I really hope this is for interest and you're not planning to use this in real code though.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64