0

Why the output between main() and func() are different? I want to get the sign bit with bitwise operation and '+'operation, so I use this statement: (x >> 31) & 0x1 to determine whether the sign bit is 1, and its worked well in the past, but today I meet this problem, why the output are different?

  #include <stdio.h>
    int func(int x)
    {
    printf("func:\n");

int minint = 0x1 << 31;
int addx = x + minint;

printf("x = %.8x\n", x);
printf("x + minint = %.8x\n",addx);
printf("right shift: %.8x\n",addx >> 31);
}

output:

func:
x = 80000000
x + minint = 00000000
right shift: ffffffff

int main()
{
    printf("main:\n");
int x = 0x80000000;
int minint = 0x1 << 31;
int addx = x + minint;
printf("x = %.8x\n", x);
printf("x + minint = %.8x\n",addx);
printf("right shift: %.8x\n",addx >> 31);
func(0x80000000);
return 0;
}

output:

main:
x = 80000000
x + minint = 00000000
right shift: 00000000
Castle
  • 1
  • 1
  • 3
    Shifting into (or out of) the sign bit (bit 31 of a 32-bit integer) is undefined behaviour. Anything can happen. Maybe - just maybe - in your case, the compiler is doing the `main` calculation at compile time (because it can) but leaving the `func` calculation to run time. – Adrian Mole Apr 20 '22 at 09:03
  • On my set up I get the same output. What if you change all the `int`s to `long`s (assuming `long` is wider than `int` on your system) and instead of `%.8x` you use `%.8lx`? – OTheDev Apr 20 '22 at 09:06
  • Also, the `%x` format is for **unsigned** types. – Adrian Mole Apr 20 '22 at 09:08
  • oh my complier is gcc on windows10, maybe this problem is from different complier? – Castle Apr 20 '22 at 09:09
  • 2
    It is *undefined* behaviour. So the result may differ with the phase of the moon. It not the compiler which is a problem, but the code. – Weather Vane Apr 20 '22 at 09:10
  • so if I want to get the sign bit, how to get the correct answer? – Castle Apr 20 '22 at 09:13
  • Start with `0x1u << 31`. That's well-defined and upon assignment to int, you end up with an unsigned to signed conversion which is implementation-defined (meaning compiler-specific, rather than undefined behavior meaning bug). Right-shifting a negative int is also implementation-defined, it could result in either arithmetic or logical shift. As you might realize by now, shifting signed integers in C is not a brilliant idea in general. – Lundin Apr 20 '22 at 09:15
  • I cannot reproduce the problem here. See https://godbolt.org/z/h4avd9bqs – Bodo Apr 20 '22 at 09:20
  • Please [edit] your question and explain what you want to achieve in the end. What do you mean with "I want to get the sign bit". One way to get the sign in a portable way is `sign = (x < 0) ? 1 : 0;` (The compiler will do the optimization.) – Bodo Apr 20 '22 at 09:34
  • @Bodo This is also portable (but ugly): `#define SHIFT (CHAR_BIT*sizeof(int)-1)` ... `_Bool sign = x & (1u << SHIFT)`. – Lundin Apr 20 '22 at 12:47
  • @Lundin My main point is that it is not necessary to use bit shifting in the C source. With a decent optimizing compiler, readable C code may result in the same machine code. See e.g. https://godbolt.org/z/hMo5hKqMb – Bodo Apr 20 '22 at 15:49
  • @Castle What's the reason for the restriction in the requirement "I want to get the sign bit *with bitwise operation and '+'operation*"? Look at the generated code: http://godbolt.org/z/hMo5hKqMb You can choose different compilers. Most compilers produce the same assembly code for the two functions. – Bodo Apr 20 '22 at 15:54

0 Answers0