-1

For example:

printf("%d", -1 & 3); 

The output is 3. I tried with other number and it's the same. sorry for short question, but I don't think I should make it long for no reason.

I searched around and did not find answer to it.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Clock
  • 3
  • 2
  • 3
    Negative one is all bits set to 1, under two's complement rules. `&` all bits set to 1 with any number and you will get that same number back. – Robert Harvey Mar 09 '23 at 11:32
  • This behavior is implementation-defined since the C standard does not require that negative numbers are represented using two's complement. – nielsen Mar 09 '23 at 11:38
  • 1
    @nielsen 99.999% of the time your machine uses two's complement. – iBug Mar 09 '23 at 11:41
  • 1
    @nielsen from C23 integer storage must be two's complement. – Weather Vane Mar 09 '23 at 11:41
  • @WeatherVane That is correct. It is a new requirement in C23 which simplifies many aspects of signed integers. – nielsen Mar 09 '23 at 11:44
  • 1
    This seems like something that is immediately obvious if you know: [What is “two's complement”?](https://stackoverflow.com/q/1049722/364696) and [Understanding the bitwise AND Operator](https://stackoverflow.com/q/3427585/364696). You won't learn much from a single example, but knowing those two things will explain any question in this realm. – ShadowRanger Mar 09 '23 at 11:44
  • 1
    @iBug: Re “99.999% of the time your machine uses two's complement”: I ran a test 100,000 times, and not once did my machine use one’s complement or sign-and-magnitude. – Eric Postpischil Mar 09 '23 at 11:48
  • What results were you expecting? Why do you think you might get some other result? It is unclear what an answer should explain without knowing which aspect of this operation is confusing. Is it not knowing what operation the `&` operator performs? Is it not knowing how −1 and 3 are represented in bits? Something else? – Eric Postpischil Mar 09 '23 at 11:50
  • 1
    @EricPostpischil "I ran a test..." That is the outcome you would expect in about 37% of the cases :-). Hint: 0.99999^100000 ~ 37%. – nielsen Mar 09 '23 at 11:55
  • My signed magnitude CPU used two's complement in -0% of all test cases. – Lundin Mar 09 '23 at 12:29
  • @nielson: That is the outcome you would expect in 100,000 tests of an independent event. What makes you think the events are independent? If I test the digits of my car’s odometer, I get sequential readings, not independent random numbers. – Eric Postpischil Mar 09 '23 at 12:49
  • @EricPostpischil Of course, I completely agree. My comment was meant to be sarcastic. – nielsen Mar 09 '23 at 13:10
  • 1
    @nielsen: Ditto. – Eric Postpischil Mar 09 '23 at 14:36

3 Answers3

3

Some1) (not all) of the bitwise operators don't care about signedness of the operands but instead look at the raw binary representation of the variable.

In case of the negative value -1, the raw binary in the common two's complement format looks as 1111....1111 (all ones).

As an example, lets assume 16 bit int, 2's complement:

Dec   Bin
-1    1111 1111 1111 1111
 3    0000 0000 0000 0011
-------------------------
 &    0000 0000 0000 0011 = 3 dec

1) Specifically, & | ^ ~ and their compound assignment equivalents only look at the raw binary representation.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Actually, if the other operand is an unsigned integer (e.g. `3u`), then `-1` would first be converted to an unsigned integer with the value `UINT_MAX` according to the usual arithmetic conversions so in that case the binary representation of negative integers would not be an issue. – nielsen Mar 09 '23 at 12:19
  • @nielsen That conversion is however well-defined and as it happens, it is done (as per modulus UINT_MAX+1) in a way equivalent of taking the raw binary representation and storing it in an unsigned type. With two's complement you won't notice the difference. – Lundin Mar 09 '23 at 12:23
  • That was my point. Since we are still under C17 (as far as I know), two's complement is not required by the standard, but the conversion would get around that. – nielsen Mar 09 '23 at 12:29
  • @nielsen Well... C23 is in "stage 30.60" https://www.iso.org/standard/82075.html. It has to run the ISO gauntlet of bureaucracy. Roughly equivalent to the 9 gates of hell. By the time an ISO standard has been published, it is time to revise it again, because the technology covered by it has become outdated at that point... – Lundin Mar 09 '23 at 12:41
0

Because it is bitwise operation. Two complement's negative numbers have the most significant bit set, positive have this bit set to zero.

If you 1 & 0 the result will be always zero. So after this operation the MSB will be zero and the integer will be positive

Example (x - does not matter)

1xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - negative number 0xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - positive number

1xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx (negative) & 0xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx (positive) = 0xxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx (positive)

0___________
  • 60,014
  • 4
  • 34
  • 74
0

Why "-1 & positive integer" always return the positive integer?

C allows various int encodings. All have a sign bit. "There shall be exactly one sign bit." Only with that bit set may the value be negative.

Using & will never set any bit including the sign bit. & will only reduce - or keep the same - the bits that are set.

"anything & positive integer" will always result in a positive (non-negative) number.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256