1

I have the following code:

unsigned int m_font_timer = 0;

int Getsum(int p_top_left_x)
{
    int l_sum = (((p_top_left_x + (m_font_timer >> 2)) & 0x7) - 4 ) >> 2;
    
    if (l_sum < 0) l_sum = -l_sum;
    return l_sum;
}

Unless I explicitly cast m_font_timer to (signed int) this part of the expression becomes unsigned:

((p_top_left_x + (m_font_timer >> 2)) & 0x7) - 4 );

Even though there is a "-4" and p_top_left_x is signed.

This is happening on a crosscompiler for SH4 using gcc 4.7.3 (I'm programming for an old system that requires it). I wasn't expecting that part to turn into unsigned. I have this code running on two other platforms also with GCC (higher version than this one) and one with MSCV and they all keep the aforementioned expression as signed.

I don't know much about compilers, is this undefined behavior? Is there any way the compiler would warn me about this? I have -Wall -Wformat=0 -Wextra -Wsign-compare but doesn't rise any warnings in that function.

Thanks!

Walrfi
  • 113
  • 6
  • 2
    it is well-defined behaviour. `- 4` is not negative number only you subtract `4` from the unsigned number. Because unsigned expression on the right side of the assignment is not larger than INT_MAX, `l_sum` is not negative – 0___________ Aug 19 '21 at 09:03
  • Bear in mind that signed right shift is implementation-defined. – 0___________ Aug 19 '21 at 09:07
  • Thanks for the answer! Wouldn't l_sum be negative when (p_top_left_x + (m_font_timer >> 2)) & 0x7) results to 0? Then it would be ((0 -4) >> 2) I'm just confused how that expression before the last ">> 2" can ouput a signed or signed result depending on the compiler and still be defined – Walrfi Aug 19 '21 at 09:17
  • 2
    signed `>>2` is **implementation defined** so every implementation can implement it its own way – 0___________ Aug 19 '21 at 09:25

1 Answers1

2

Type conversion works by rank and signedness: If the types are of different rank - as in int and char, the lower rank (char) will get converted to the higher rank (int).

If both types are of the same rank but the sign is different - the signed type will be converted to unsigned unless explicitly stated otherwise.

Here are a few places which explain in detail:

usual arithmatic conversion

another source

Dharman
  • 30,962
  • 25
  • 85
  • 135
Uriel.Gi
  • 69
  • 1
  • 6
  • Thanks for the answer, much appreciated! So basically m_font_timer is turning the whole expression to unsigned before the last >>2 right? But shouldn't this happen for the other 2 platforms where I'm using a newer version of GCC? – Walrfi Aug 19 '21 at 09:20
  • 1
    Its a little hard to try and tell what happens in the other platforms, but the different behavior is in the two others. The conversion to unsigned is expected produces the expected result on my computer too. – Uriel.Gi Aug 19 '21 at 09:34