As already explained by other answers, the cause are usual arithmetic conversions, the type size_t obtained using sizeof
causes int to get converted to unsigned type corresponding to type size_t.
I would like to add that the behavior is implementation defined1. The loop can be taken or not. This depends on the definition of the type size_t.
C Standard permits that type size_t has a lower rank than type int. In that case integer promotions promote the type size_t to type int. At that point both sides have the same type int, so the conversions stop. The comparison d <= (TOTAL_ELEMENTS - 2)
then yields true, and the loop is taken.
1 The program is therefore not strictly conforming as the output relies on implementation-defined behavior.