1

What will be the output of the following C program?

main()
{
    char g[] = "geeksforgeeks";
    printf("%s", g + g[6] - g[8]);
}
  1. geeks
  2. rgeeks
  3. geeksforgeeks
  4. forgeeks

The answer is 1: geeks.

But I had an argument with someone that he said it is undefined behaviour. So is it undefined behaviour or not?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 1
    There's definitely a dupe somewhere, but pointer addition and subtraction aren't allowed to produce an out-of-bounds pointer even if you bring it back in bounds before dereferencing it. – chris Jul 29 '20 at 06:20
  • 1
    (As some answers suggest, even if there was no issue with temporary pointers pointing outside the array) There is no guarantee that `'o'-'g'` yields a small(ish) positive value. On some implementation it can yield a large(ish) or negative value ... and therefore invoke UB. – pmg Jul 29 '20 at 06:27
  • @pmg can you elaborate a little on that..I didn't understand how 'o'-'g' can be a large value? won't it always be 8? – Vishal Sharma Jul 29 '20 at 06:30
  • 2
    @VishalSharma I believe (some) current IBM mainframes still use [EBCDIC character set](http://ascii-table.com/ebcdic-table.php). On those computers `'o' - 'g'` yields 15. *On a Klingon computer with a C compiler implementation it might yield `-77` for example*. The C Standard allows letters `'a'` to `'z'` (or uppercase) to not be sequential, to have "holes" – pmg Jul 29 '20 at 06:33

1 Answers1

1

This statement involving pointer arithmetic is UB, because of the associativity of + operator.

In this case (considering ASCII encoding)

  • g[6] is o, which has a decimal value of 111
  • g[8] is g, which has a decimal value of 103

So, finally the construct looks like

printf("%s", g + 'o' - 'g');

which is same as

printf("%s", (g + 111) - 103);

here, g+111 points way past the array (note: arithmetic involving only one element past the array is valid), so this would be UB.

However, if we modify the statement like

printf("%s", g + (g[6] - g[8])); //enforcing precedence

which is same as

printf("%s", g + 8);

or

printf("%s", &(g[8]));

then it will be valid. However, if there's other encoding systems in use, and (g[6] - g[8]) does not yield a value which is within the array bounds, it'll again be UB for the same reason as the original statement.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261