QBitArray
은 다른 것으로 변환 할 수 있도록 설계되지 않았습니다. 내부 표현은 실제로 내부적입니다.
아아, 비트 검사는 비교적 쉽습니다. 현대 건축물은 배럴 쉬프터를 사용하므로 변속이 저렴합니다.
가능한 비트 - 바이트 매핑은 여러 가지가 있습니다. 의 그들 모두를 커버하자 따라서
byte 0 byte 1 byte n-1 byte n
LL - [] [89ABCDEF] ...
LB - [] [FEDCBA98] ...
BL - ... [89ABCDEF] []
BB - ... [FEDCBA98] []
:
enum class BitMapping { LL, LB, BL, BB };
bool getBit1(const QByteArray & arr, int bit, BitMapping m) {
Q_ASSERT(arr.size() >= 8);
auto byte = (m == BitMapping::LL || m == BitMapping::LB) ?
bit/8 : (7 - bit/8);
bit = (m == BitMapping::LB || m == BitMapping::BB) ?
(bit%8) : (7 - (bit%8));
return arr.at(byte) & (1<<bit);
}
우리는 플랫폼은 64 비트 정수에 대한 합리적인 지원이 있다고 가정한다면, 우리는 그 활용 할 수 있습니다
bool getBit2(const QByteArray & arr, int bit, BitMapping m) {
Q_ASSERT(arr.size() >= 8);
auto value = *reinterpret_cast<const quint64 *>(arr.data());
if (m == BitMapping::LL || m == BitMapping::BL)
bit = (bit & 0x38) + 7 - (bit & 0x07); // reorder bits
if ((Q_BYTE_ORDER == Q_LITTLE_ENDIAN && (m == BitMapping::BL || m == BitMapping::BB)) ||
(Q_BYTE_ORDER == Q_BIG_ENDIAN && (m == BitMapping::LL || m == BitMapping::LB)))
bit = (bit & 0x07) + 0x38 - (bit & 0x38); // reorder bytes
return value & (1<<bit);
}
하나를 알맞은 컴파일러는 위의 두 가지 구현 모두를 전문화 할 때 인라인 할 것이다.
bool getBit(const QByteArray & arr, int bit) {
return getBit2(arr, bit, BitMapping::LB);
}
또한 LB
경우에 손으로 전문 수 있습니다 다음 Q_BYTE_ORDER
검사가 컴파일시 일정하고 어떤 런타임 오버 헤드가 발생 없다는 것을
bool getBit1(const QByteArray & arr, int bit) {
Q_ASSERT(arr.size() >= 8);
auto byte = bit/8;
bit = bit%8;
return arr.at(byte) & (1<<bit);
}
bool getBit2(const QByteArray & arr, int bit) {
Q_ASSERT(arr.size() >= 8);
auto value = *reinterpret_cast<const quint64 *>(arr.data());
if (Q_BYTE_ORDER == Q_BIG_ENDIAN)
bit = (bit & 0x07) + 0x38 - (bit & 0x38); // reorder bytes
return value & (1<<bit);
}
참고.
getBit1
및 getBit2
Qt를가 실행되는 모든 플랫폼에 이식하고, getBit2
는 getBit1
보다 조금 더 나은 코드를 생성합니다. x86-64에서 getBit2
의 비트 트위 들링 코드는 5 명령어 수입니다.
mov $0x1,%eax
shl %cl,%eax
cltq
test %rax,(%rdi)
setne %al
retq
질문에 현재 코드를 추가하십시오. 왜 비트 연산자를 사용하여 비트 값을 알 수 없는지 궁금합니다. http://stackoverflow.com/a/523737/2266412 –
그 이유는'int'를 받아 들여 원시 QByteArray 비트 검사를 찾고 있기 때문입니다. 먼저 비트가있는 특정 바이트를 찾고 int로 변환 한 다음 해당 메서드를 사용해야합니다. 바이트 위치와 비트 위치는 논리를 이해할 필요가있다. 성능이 중요하므로 더 직접적이고 더 빠른 것을 원합니다. 저는 현재 코드에 대해 설명했으며, 전혀 사용하지 않을 것입니다. 지저분해서 게시하는 것이 전혀 도움이되지 않을 것이라고 생각합니다. – mrg95
당신이 말하는 "논리"는 현대 CPU에서는 사소한 것입니다. https : // godbolt로 이동해야합니다.org를 방문하여 직접 확인하십시오. –