C++ bit级别的复制

184 阅读2分钟

初步实现:

void bitCopy(unsigned char *src, int srcStartBit, unsigned char *dest, int destStartBit, int numBits) {
    // 计算源字节和目标字节的起始位置
    int srcStartByte = srcStartBit / 8;
    int destStartByte = destStartBit / 8;
    
    // 计算源字节和目标字节内的起始位的偏移量
    int srcStartOffset = srcStartBit % 8;
    int destStartOffset = destStartBit % 8;
    
    // 循环复制每一位
    for (int i = 0; i < numBits; i++) {
        // 计算当前位在源字节和目标字节中的位置
        int srcBitPos = srcStartOffset + i;
        int destBitPos = destStartOffset + i;
        
        // 计算当前位所在的源字节和目标字节的索引
        int srcByteIndex = srcStartByte + srcBitPos / 8;
        int destByteIndex = destStartByte + destBitPos / 8;
        
        // 提取源字节中的当前位
        int srcBit = (src[srcByteIndex] >> (7 - srcBitPos % 8)) & 1;
        
        // 将目标字节中的当前位设置为源字节中的当前位
        dest[destByteIndex] = (dest[destByteIndex] & ~(1 << (7 - destBitPos % 8))) | (srcBit << (7 - destBitPos % 8));
    }
}

这个函数的实现步骤如下:

  1. 计算源字节和目标字节的起始位置,即 srcStartBit 和 destStartBit 除以8的商。

  2. 计算源字节和目标字节内的起始位的偏移量,即 srcStartBit 和 destStartBit 除以8的余数。

  3. 循环复制每一位,共复制 numBits 位:

    • 计算当前位在源字节和目标字节中的位置,即起始偏移量加上当前位的索引。
    • 计算当前位所在的源字节和目标字节的索引,即起始字节加上当前位置除以8的商。
    • 使用位运算提取源字节中的当前位。
    • 使用位运算将目标字节中的当前位设置为源字节中的当前位。

这个实现考虑了源位和目标位可能跨越字节边界的情况,通过位运算实现了位级别的复制。

请注意,这个实现假设源位和目标位的范围是合法的,即不会越界访问内存。如果需要更严格的边界检查,可以在函数开头添加相应的断言或错误处理逻辑。

优化

// 优化后的函数实现
void bitCopyOptimized(unsigned char* src, int srcStartBit, unsigned char* dest, int destStartBit, int numBits) {
    int srcBitOffset = srcStartBit % 8;
    int destBitOffset = destStartBit % 8;
    int srcByteOffset = srcStartBit / 8;
    int destByteOffset = destStartBit / 8;

    while (numBits > 0) {
        int bitsToCopy = std::min(8 - srcBitOffset, 8 - destBitOffset);
        bitsToCopy = std::min(bitsToCopy, numBits);

        unsigned int srcMask = ((1 << bitsToCopy) - 1) << (8 - srcBitOffset - bitsToCopy);
        unsigned int destMask = ((1 << bitsToCopy) - 1) << (8 - destBitOffset - bitsToCopy);

        unsigned char srcBits = (src[srcByteOffset] & srcMask) >> (8 - srcBitOffset - bitsToCopy);
        dest[destByteOffset] = (dest[destByteOffset] & ~destMask) | (srcBits << (8 - destBitOffset - bitsToCopy));

        numBits -= bitsToCopy;
        srcBitOffset += bitsToCopy;
        destBitOffset += bitsToCopy;

        if (srcBitOffset >= 8) {
            srcBitOffset -= 8;
            srcByteOffset++;
        }
        if (destBitOffset >= 8) {
            destBitOffset -= 8;
            destByteOffset++;
        }
    }
}

测试:

void testTime()
{
	const int dataSize = 512;
	unsigned char src[dataSize];
	unsigned char destOriginal[dataSize];
	unsigned char destOptimized[dataSize];

	// 初始化数据
	for (int i = 0; i < dataSize; ++i) {
		src[i] = i % 256;
		destOriginal[i] = 0;
		destOptimized[i] = 0;
	}

	int srcStartBit = 5;
	int destStartBit = 3;
	int numBits = dataSize -8;

	// 测试原始函数
	auto startOriginal = std::chrono::high_resolution_clock::now();
	bitCopy(src, srcStartBit, destOriginal, destStartBit, numBits);
	auto endOriginal = std::chrono::high_resolution_clock::now();
	std::chrono::duration<double> durationOriginal = endOriginal - startOriginal;
	std::cout << "Original function duration: " << durationOriginal.count()*10000 << " seconds\n";

	// 测试优化后的函数
	auto startOptimized = std::chrono::high_resolution_clock::now();
	bitCopy2(src, srcStartBit, destOptimized, destStartBit, numBits);
	auto endOptimized = std::chrono::high_resolution_clock::now();
	std::chrono::duration<double> durationOptimized = endOptimized - startOptimized;
	std::cout << "Optimized function duration: " << durationOptimized.count() * 10000 << " seconds\n";
}