부울 크기가 1 비트가 아닌 1 바이트 인 이유는 무엇입니까?


127

C ++에서

  • 부울 크기가 1 비트가 아닌 1 바이트 인 이유는 무엇입니까?
  • 4 비트 또는 2 비트 정수와 같은 유형이없는 이유는 무엇입니까?

CPU 용 에뮬레이터를 작성할 때 위의 내용을 놓치고 있습니다.


10
C ++에서는 비트 필드를 사용하여 데이터를 "포장"할 수 있습니다. struct Packed { unsigned int flag1 : 1; unsigned int flag2: 1; };. 대부분의 컴파일러는 full을 할당 unsigned int하지만 읽기 / 쓰기시 자체적으로 비트 트위들 링을 처리합니다. 또한 그들은 모듈로 연산을 스스로 처리합니다. 그건입니다 unsigned small : 4:) 속성이 0에서 15 사이의 값을 가지고 있으며, 그것은 16에 도착해야 할 때, 그것은 앞의 비트를 덮어 쓰지 않습니다
마티유 M.

답변:


208

CPU는 1 바이트보다 작은 것을 처리 할 수 ​​없기 때문입니다.


10
젠장, 지금은 어색합니다 선생님
Asm

31
사실, 네 개의 86 지침 bt, bts, btrbtc 수있는 하나의 비트를 해결!
fredoverflow

11
생각 bt바이트 오프셋 주소를 다음 얻을 것 주어진 오프셋, 당신은 바이트에 가서 주소를 지정하는 경우에 관계없이, ... 비트 오프셋 (offset) 리터럴의 비트를 테스트 비트 말의을 (말장난을 변명).
user7116 2011 년

2
@six : 하나의 레지스터에 배열의 시작 부분을로드 한 다음 상대 "비트 오프셋"을 초에로드 할 수 있습니다. 비트 오프셋은 "1 바이트 이내"로 제한되지 않으며 32 비트 숫자 일 수 있습니다.
fredoverflow

4
글쎄, 예 그리고 아니오. 우리는 비트 필드를 가지고 있고, 주소 + 비트 번호 인 비트 필드 포인터를 가질 수 있습니다. 분명히 이러한 포인터는 비트 번호에 대한 추가 저장 요구 사항으로 인해 void *로 변환 할 수 없습니다.
Maxim Egorushkin 2011 년

32

에서 위키 백과 :

역사적으로 바이트는 컴퓨터에서 텍스트의 단일 문자를 인코딩하는 데 사용되는 비트 수였으며 이러한 이유로 많은 컴퓨터 아키텍처에서 기본 주소 지정 요소 입니다.

바이트가되도록 기본 주소 지정 단위는 , 그 이하의 컴퓨터 아키텍처는 주소 수 없습니다. 그리고 4 비트 바이트를 지원하는 컴퓨터가 (아마도) 존재하지 않기 때문에 4 비트 등 이 없습니다 . bool

그러나 4 비트를 기본 주소 지정 단위로 지정할 수있는 아키텍처를 설계 할 수 있다면 bool해당 컴퓨터에서만 4 비트 크기 를 갖게 됩니다!


4
"그러면 해당 컴퓨터에서만 크기가 4 비트 인 int를 갖게됩니다."-표준이 CHAR_BIT가 8 미만이되는 것을 금지하기 때문에 그렇지 않습니다. 아키텍처의 주소 지정 단위가 8 비트 미만인 경우 C ++ 구현은 기본 하드웨어의 메모리 모델과 다른 메모리 모델을 제시하면됩니다.
Steve Jessop 2011 년

@Steve : 죄송합니다 ... 나는 그것을 간과했습니다. 제거 intchar내 게시물에서.
Nawaz 2011 년

1
아키텍처가 자체 opcode로 무엇을 처리 할 수 ​​있는지에 관계 없이은 C ++에서 가장 작은 주소 지정 가능 단위 bool이기 때문에 4 비트도 가질 수 없습니다 . 적어도 1의 값을 가져야하고 인접 객체는 C ++에서 자체 주소 가져야 하므로 구현시 더 크게 만들고 메모리를 낭비하면됩니다. 이것이 비트 필드가 특별한 경우로 존재하는 이유입니다. 구조체의 비트 필드 멤버는 별도로 주소 지정이 가능할 필요가 없으므로 a보다 작을 수 있습니다 (전체 구조체는 여전히 그럴 수 없습니다). charsizeof(bool)boolchar
Steve Jessop 2011 년

@ Steve Jessop : 흥미로워 보입니다. charC ++에서 가장 작은 주소 지정 단위 라고 말하는 언어 사양의 참조를 알려주시겠습니까 ?
Nawaz 2011 년

3
가장 가까운 특정 문장은 아마도 3.9 / 4 일 것입니다. "T 유형의 객체의 객체 표현은 T 유형의 객체가 차지하는 N 개의 부호없는 char 객체의 시퀀스입니다. 여기서 N은 sizeof (T)와 같습니다." 분명히 sizeof(bool)0.5 일 수는 없습니다. :-) 구현이 합법적으로 하위 바이트 포인터를 확장으로 제공 할 수 있다고 생각하지만, 일반적인 방법으로 할당 된 bool과 같은 "일반"객체는 표준이 말하는대로 수행해야합니다.
Steve Jessop 2011 년

12

가장 쉬운 대답은 다음과 같습니다. CPU가 메모리를 비트가 아닌 바이트로 주소 지정하고 비트 연산이 매우 느리기 때문입니다.

그러나 C ++에서 비트 크기 할당을 사용할 수 있습니다. 비트 벡터에 대한 std :: vector 특수화가 있으며 비트 크기 항목을 취하는 구조체도 있습니다.


1
비트 연산이 느리다는 데 동의할지 모르겠습니다. ands, nots, xors 등은 매우 빠릅니다. 일반적으로 느린 비트 연산의 구현입니다. 기계 수준에서는 매우 빠릅니다. 분기 ... 이제는 느립니다.
Hogan 2011 년

3
더 명확하게 말하면, 부울 벡터를 생성하고 부울 24 개를 넣으면 3 바이트 (3 * 8) 만 사용됩니다. 다른 부울을 넣으면 다른 바이트가 사용됩니다. 그러나 다른 부울을 푸시하면 마지막 바이트에서 "free"비트를 사용하기 때문에 추가 바이트가 필요하지 않습니다
Pedro Loureiro

그래, 나는 또한 bitewise 작업 : 느린 의심
페드로 Loureiro

비트 벡터는 비트 크기 할당을 생성하지 않습니다. 그들은 바이트 크기 할당을 만듭니다. 단일 비트를 할당 할 수 없습니다.
John Dibling 2011 년

1
비트 벡터에서 단일 비트를 읽으려면 시프트 및 다시 시프트의 세 가지 연산이 필요합니다. 쓰기는 두 가지입니다. 개별 바이트는 단일 바이트로 액세스 할 수 있습니다.
sukru

7

예전에는 눈보라 속에서 양쪽으로 오르막길을 걸어 가야했고 점심은 학교 뒤의 숲에서 추적하고 맨손으로 죽일 수있는 동물이었습니다. 컴퓨터는 사용 가능한 메모리가 훨씬 적었습니다. 오늘. 내가 사용한 첫 번째 컴퓨터에는 6K의 RAM이있었습니다. 6 메가 바이트가 아니라 6 기가 바이트, 6 킬로바이트가 아닙니다. 이 환경에서는 가능한 한 많은 부울을 int에 압축하는 것이 합리적 이었으므로 정기적으로 연산을 사용하여이를 꺼내고 넣었습니다.

오늘날 사람들이 1GB의 RAM 만 가지고 있다고 조롱하고 200GB 미만의 하드 드라이브를 찾을 수있는 유일한 곳은 골동품 가게뿐입니다.


플래그를 다루는 경우를 제외하고. 무언가에 여러 옵션을 설정하는 것과 같은 것 ... 예. 00000001 + 00000100 = 00000101.
Armstrongest

@Atomix : 나는 더 이상 이것을 거의하지 않습니다. 두 개의 플래그가 필요한 경우 두 개의 부울 필드를 만듭니다. 나는 그런 플래그를 포장 한 다음 "if flags & 0x110! = 0 then"등을 작성하는 코드를 작성하곤했지만 이것은 비밀스럽고 요즘에는 일반적으로 별도의 필드를 만들고 "if fooFlag || barFlag "대신. 어떤 이유로 든 이와 같은 플래그를 패킹하는 것이 더 나은 경우의 가능성을 배제하지는 않지만 예전처럼 메모리를 절약 할 필요가 없습니다.
Jay

2
사실,이다 확실히 당신이 메모리에 저장하는 데이터의 많은 양에 - 당신은 당신의 계산이 빨리하려면, 비트를 팩에 문제가 가치. 부울을 패킹하는 것은 더 작은 저장소만을위한 것이 아닙니다. 즉, 압축을 풀 때보 다 8 배 더 빠르게 (대역폭 측면에서) 부울 입력 배열을 읽을 수 있으며 이는 종종 매우 중요합니다. 또한 CPU 자체에서 작업 속도를 높이는 popc (인구 수)와 같은 비트 연산을 사용할 수 있습니다.
einpoklum

2
정말 엄청난 수의 부울은 DBMS, 기계 학습, 과학 시뮬레이션 및 기타 여러 가지 작업을 수행하는 경우 매일 작업하는 것입니다. 그리고-그저 작업 하는 것은 메모리에서 캐시로 복사하는 것을 의미합니다. 백만불은 아무것도 아닙니다.
einpoklum

1
@PeterCordes 예, 당연히, 논리적으로 "동일한 아이디어"인 부울 세트가있어서 자연스럽게 어떤 의미에서 "배열"로 생각하고 마스크하거나 필터링하거나 그렇지 않으면 비트 연산을 수행 한 다음 바이트로 패킹하는 것이 좋습니다. 앞서 말했듯이, 이러한 조건이 적용되는 애플리케이션에서 마지막으로 작업했을 때를 생각하기가 힘들지만 몇 가지 좋은 예를 들려 주면 다른 사람을 생각할 수있는 약간의 상상력이 있다고 확신합니다.
Jay

6

비트 필드를 사용하여 하위 크기의 정수를 얻을 수 있습니다.

struct X
{
    int   val:4;   // 4 bit int.
};

일반적으로 정확한 하드웨어 예상 비트 패턴에 구조를 매핑하는 데 사용되지만 :

struct SomThing   // 1 byte value (on a system where 8 bits is a byte
{
    int   p1:4;   // 4 bit field
    int   p2:3;   // 3 bit field
    int   p3:1;   // 1 bit
};

6

1 비트 부울과 4 비트 및 2 비트 정수를 가질 수 있습니다. 그러나 그것은 아키텍처를 보는 부 자연스러운 방법이기 때문에 성능 향상이없는 이상한 명령 세트를 만들 것입니다. 실제로 사용하지 않는 데이터를 회수하는 것보다 바이트의 더 나은 부분을 "낭비"하는 것이 합리적입니다.

내 경험상 여러 부울을 단일 바이트로 압축하는 데 방해가되는 유일한 앱은 Sql Server입니다.


6

바이트는 언어에서 가장 작은 주소 지정 단위이기 때문입니다.

그러나 예를 들어 한 묶음이 있으면 bool을 1 비트로 만들 수 있습니다. 다음과 같이 구조체에서 :

struct A
{
  bool a:1, b:1, c:1, d:1, e:1;
};

2

bool1 바이트 (CPU의 주소 지정 가능한 가장 작은 크기)이거나 더 클 수 있습니다. 성능을 위해 bool크기가되어야하는 것은 드문 일이 아닙니다 int. 특정 목적 (예 : 하드웨어 시뮬레이션)을 위해 N 비트 유형이 필요한 경우이를위한 라이브러리를 찾을 수 있습니다 (예 : GBL 라이브러리에 BitSet<N>클래스가 있음). 크기에 관심이 있다면 bool(아마도 큰 용기를 가지고있을 것입니다.) 직접 포장하거나 std::vector<bool>그것을 사용하여 사용할 수 있습니다.


2

에뮬레이터 수준에서이를 구현하는 방법에 대해 생각해보십시오.

bool a[10] = {false};

bool &rbool = a[3];
bool *pbool = a + 3;

assert(pbool == &rbool);
rbool = true;
assert(*pbool);
*pbool = false;
assert(!rbool);

2

일반적으로 CPU는 MIPS와 같은 일부 CPU가 4 바이트 워드를 사용하지만 기본 단위로 1 바이트로 메모리를 할당하기 때문입니다.

그러나 vector거래 bool와 특별한 방식으로 vector<bool>각 부울 하나의 비트가 할당된다.


1
성능 저하가 있지만 MIPS CPU조차도 개별 바이트에 대한 액세스를 제공 할 것이라고 생각합니다.
Paul Tomblin 2011 년

@Paul : 예, 맞습니다. 그러나 일반적으로 단어 별 lw/ sw이 훨씬 더 널리 사용됩니다.
Ryan Li

MIPS에 대해 모르지만 IA-64 아키텍처는 64 비트 경계에서만 액세스를 허용합니다.
Gene Bushuyev 2011 년

0

바이트는 컴퓨터의 더 작은 디지털 데이터 저장 단위입니다. 컴퓨터에서 RAM은 수백만 바이트를 가지고 있으며 누구에게나 주소가 있습니다. 모든 비트에 대한 주소가 있다면 컴퓨터는 가능한 것보다 8 배 적은 RAM을 관리 할 수 ​​있습니다.

더 많은 정보 : Wikipedia


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.