4

I tried rewriting the small C program below in Python, but I am getting different outputs.

C version:

#include <stdio.h>

int main()
{
  unsigned char data = 0x00;
  unsigned char i;
  unsigned char bit = 0x01;
  unsigned char parity = 1;

  unsigned char value = 0x1c;

  for (i = 0; i < 8; i++)
  {
    data = data | bit;
    bit = bit << 1;
    parity = parity ^ (data & 0x01);
  }

  printf("data: %d bit: %d parity: %d\n", data, bit, parity);

  return 0;
}

Python version:

data = 0
bit = 1
parity = 1
value = int('1c', 16)

for i in range(8):
  data = data | bit
  bit = bit << 1
  parity = parity ^ (data & 1)

print('data: {0} bit: {1} parity: {2}'.format(data, bit, parity))

And the outputs are:

C version

> $ ./test
data: 255 bit: 0 parity: 1

Python version

> $ python3 test.py
data: 255 bit: 256 parity: 1

What am I missing on Python bitwise operations?

3
  • You're missing 'ctypes' Commented Nov 23, 2018 at 1:17
  • 2
    You are missing that your type is larger than a byte. As such: 128 << 1 = 256 and does not overflow to 0 Commented Nov 23, 2018 at 1:25
  • @planetmaker, yep; ctypes module is somewhat awkward but consistent way to deal with it. Although not "pythonic" at all ) Commented Nov 23, 2018 at 1:44

1 Answer 1

9

As you can see, the only difference in the output is the value of the variable bit.

In your C program, the variable bit is declared as unsigned char. That means it takes on only the values 0 through 255. The last operation on bit in your code is

bit = bit << 1

Before the last time that line is executed, bit is 128. After that line, it "tries" to become 256 but that does not fit into an unsigned char. So overflow happens, not flagged by your program, and bit becomes 0.

In the Python program, the variable bit is simply an integer, int, which has no maximum size. So there is no overflow, and bit does become 256.

There are several ways to overcome that difference in Python. You could force bit to stay in the desired range by instead using

bit = (bit << 1) % 256

or perhaps

bit = (bit << 1) & 255

You could instead make bit to be the equivalent of an unsigned char variable. As a comment says, you could use the ctypes module, I believe. You could also use numpy (I'm more familiar with that).

Sign up to request clarification or add additional context in comments.

5 Comments

Exactly, Python is not aware about "small" integer types…
@RoryDaulton Maybe you should rephrase it, considering google will match this some day: "In the Python program, bit is just an integer."
@agg3l: I rephrased it. Is that what you meant?
@RoryDaulton Confusing naming of variables in Python code sample (assuming byte-aware integer types, which are not really there) by kolrie has already and may lead to more confusion later. As long as Python is not low-level language by design. That was my idea
@RoryDaulton Just think of (yours) quote "bit [value] is 128"… What ???. It does not applies to yours answer which is absolutely correct; the form only. Forget it, sorry

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.