1

How can I do memcpy but for bits instead of bytes?

Here is a mockup function I wrote. It is probably not very efficient.

How would you do that ? Is there a better or more efficient way?

void * memcpyBits (
  void * destination, // pointer to bytes array
  size_t destinationStart, // start offset in bits
  const void * source, // pointer to bytes array
  size_t sourceStart, // start offset in bits
  size_t length )  // length in bits
{
  int i;
  const uint8_t * sourceByte;
  uint8_t * destinationByte;
  uint8_t bit;
  uint8_t destinationMask;
  for (i=0; i<length; i++) {
    sourceByte = source + (sourceStart + i) / 8;
    bit = (*sourceByte) >> 7 - (sourceStart + i) % 8;
    bit &= 0b00000001;

    destinationMask = 1 << 7 - (destinationStart + i) % 8;
    destinationByte = destination + (destinationStart + i) / 8;

    if (bit) { // is 1
      *destinationByte |= destinationMask; // set
    } else {
      *destinationByte &= ~destinationMask; // clear
    }
  }
}

Here is a sample call :

  // headingAvg, 9 bits, 0-511
  uint16_t packedHeadingAvg = (float)(headingAvg + 0.5);
  memcpyBits(message->content, message->bits, packedHeadingavg, 16-9, 9);
  message->bits += 9;
user1219721
  • 783
  • 1
  • 8
  • 16
  • Probably more efficient way will be to copy not in byte chunks but in 2-byte or 4-byte chunks (if supported). What is your ARM? What are typical argument values for the function? – osgx Nov 05 '17 at 00:34
  • we use cortex m4 – user1219721 Nov 05 '17 at 00:35
  • 1
    I'm voting to close this question as off-topic because This question belongs on code review site in the Stack Exchange network – Stargateur Nov 05 '17 at 00:37
  • @Stargateur I do not agree. I think that "how do you do memcpy for bits instead of bytes" is a general programming question – user1219721 Nov 05 '17 at 00:39
  • @user1219721 SO is only for code that don't work, here you clearly ask "Is there a better way to do that?", so you should post your question in code review. – Stargateur Nov 05 '17 at 00:42
  • 2
    if `(destinationStart % 8) == (sourceStart % 8)` then you can add an optimization which is to use `memcpy` for all the bytes in between the first and last. memcpy is typically well optimized on most platforms. – selbie Nov 05 '17 at 00:44
  • https://stackoverflow.com/a/32252918/4454124 – mnistic Nov 05 '17 at 01:19
  • Possible duplicate of ['memcpy'-like function that supports offsets by individual bits?](https://stackoverflow.com/questions/32043911/memcpy-like-function-that-supports-offsets-by-individual-bits) – Tim Nov 07 '17 at 00:48
  • Here is a might be faster implementation: https://stackoverflow.com/questions/17320643/is-it-possible-to-do-memcpy-in-bits-instead-of-bytes/71347247#71347247 – Andry Mar 04 '22 at 06:32

0 Answers0