3

Possible Duplicate:
Confused about C macro expansion and integer arithmetic
A riddle (in C)

The output of the following C program is to print the elements in the array. But when actually run, it doesn't do so.

  #include<stdio.h>

  #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
  int array[] = {23,34,12,17,204,99,16};

  int main()
  {
      int d;

      for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
          printf("%d\n",array[d+1]);

      return 0;
  }

Why is that?

Community
  • 1
  • 1
  • 1
    Is this homework? (If it is, you should tag it accordingly.) – eq- Jun 05 '12 at 15:38
  • 2
    Fantastically scary macro that includes the name of the array, instead of taking it as an argument. Very confusing. – unwind Jun 05 '12 at 15:41
  • See answer by Hari Mahadevan. Can you tell us what led you to setting variable d to -1 instead of zero? – Miguel Rentes Jun 05 '12 at 15:51
  • [cannot-enter-in-while-statement](http://stackoverflow.com/questions/10849724/cannot-enter-in-while-statement/10849748#10849748) - [unsigned-and-signed-comparison](http://stackoverflow.com/questions/3384911/unsigned-and-signed-comparison) - [unsigned-int-and-signed-char-comparison](http://stackoverflow.com/questions/5087992/unsigned-int-and-signed-char-comparison) – gliderkite Jun 05 '12 at 15:57
  • 1
    I'm curious: is this code that you wrote, and don't understand, or is this code that professor provided as a what-does-this-obscure-code-do quiz? – Robᵩ Jun 05 '12 at 16:03

7 Answers7

5

sizeof() returns unsigned int and so in the <= comparison, d gets converted to unsigned int. -1 when converted to unsigned int is 0xffffff. Since 0xffffff > (7-2), for-loop body won't be executed even once.

gliderkite
  • 8,828
  • 6
  • 44
  • 80
Hari Mahadevan
  • 920
  • 7
  • 14
  • 1
    "*-1 when converted to unsigned int is 0xffffff*" -- or `0xffff`, or `0xffffffffffffffff`, or some other number. But always a big number. – Robᵩ Jun 05 '12 at 16:05
4

This fails because sizeof is returning a value of type size_t, which is unsigned. This causes the comparison to promote the -1 to unsigned, which is generally a very large value and thus make the comparison fail.

You should receive warnings for the sign mismatch.

unwind
  • 391,730
  • 64
  • 469
  • 606
3

The point is the type of value sizeof returns.

It's a size_t, which is an unsigned type, so converting -1 to that type for the comparison produces the maximal value of the type, which is far larger than 5.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
1
for(d=-1;d <= ((int)TOTAL_ELEMENTS-2);d++)
manuskc
  • 784
  • 4
  • 14
  • I think your answer is better ;) The code is probably taken from an exam/test question with a conscious "defect". Both yours and mine suggestions are correct but this one says "you can't catch me". – ManieQ Jun 05 '12 at 20:52
1

I guess this is more clear:

for(d = 0; d < TOTAL_ELEMENTS; d++)
   printf("%d\n",array[d]);

And size_t case should not be a problem anymore.

ManieQ
  • 330
  • 2
  • 8
0

A more standard way to write this loop which works would be

for(d = 0; d < TOTAL_ELEMENTS; d++)
   ...

as was pointed out by correctly by several others here already, the problem lies with signed/unsigned values being compared. This construct would have avoided the problem.

Levon
  • 138,105
  • 33
  • 200
  • 191
0

Your original problem works, when I do the following:

#define TOTAL_ELEMENTS 7
int array[] = {23,34,12,17,204,99,16};

int main()
{
  int d;

  for(d=-1; d <= (TOTAL_ELEMENTS - 2); d++)
      printf("%d\n",array[d+1]);

  return 0;
}

This has something to do with comparing a negative number d=-1 with (TOTAL_ELEMENTS-2). I believe it might be sizeof, butI will leave finding out why as an exercise.

Leaving your original #define as it was --

#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))

-- but using zero-based indexing also worked.

I'm not sure why your original TOTAL_ELEMENTS definition caused the loop not to print.

octopusgrabbus
  • 10,555
  • 15
  • 68
  • 131