C에서 비트 필드를 언제 사용합니까?
'왜 비트 필드를 사용해야합니까?'라는 질문에 대해 Google에서 검색하면 비트 필드가 플래그에 사용된다는 것을 발견했습니다. 이제 궁금합니다. 비트 필드가 실제로 사용되는 유일한 방법입니까? 공간을 절약하기 위해 비트 필드를 사용해야합니까?
책에서 비트 필드를 정의하는 방법 :
struct {
unsigned int is_keyword : 1;
unsigned int is_extern : 1;
unsigned int is_static : 1;
} flags;
왜 int를 사용합니까? 얼마나 많은 공간을 차지하고 있습니까? 왜 우리가 int를 사용하는지 혼란 스럽지만 짧거나 int보다 작은 것이 아닙니다. 내가 이해하기 때문에 1 비트 만 메모리에 점유되지만 부호없는 정수 값 전체는 아닙니다. 맞습니까?
이제 궁금합니다. [플래그가] 비트 필드가 실제로 사용되는 유일한 방법입니까?
아니요, 플래그가 비트 필드를 사용하는 유일한 방법은 아닙니다. 플래그가 더 일반적이지만 1 비트보다 큰 값을 저장하는 데에도 사용할 수 있습니다. 예를 들면 :
typedef enum {
NORTH = 0,
EAST = 1,
SOUTH = 2,
WEST = 3
} directionValues;
struct {
unsigned int alice_dir : 2;
unsigned int bob_dir : 2;
} directions;
공간을 절약하기 위해 비트 필드를 사용해야합니까?
비트 필드는 공간을 절약합니다. 또한 바이트로 정렬되지 않은 값을 더 쉽게 설정할 수 있습니다. 비트 시프트 및 비트 연산을 사용하는 대신 .NET Framework에서 필드를 설정하는 것과 동일한 구문을 사용할 수 있습니다 struct. 이것은 가독성을 향상시킵니다. 비트 필드를 사용하면 다음과 같이 작성할 수 있습니다.
directions.bob_dir = SOUTH;
그러나 수동으로 수행하려면 다음과 같이 작성해야합니다.
#define BOB_OFFSET 2
directions &= ~(3<<BOB_OFFSET); // clear Bob's bits
directions |= SOUTH<<BOB_OFFSET;
이 향상된 가독성은 여기저기서 몇 바이트를 저장하는 것보다 더 중요합니다.
왜 int를 사용합니까? 얼마나 많은 공간을 차지하고 있습니까?
전체의 공간 int이 점유됩니다. 우리 int는 많은 경우에 실제로 중요하지 않기 때문에 사용 합니다. 단일 값에 대해 1 또는 2 대신 4 바이트를 사용하면 사용자가 알아 차리지 못할 것입니다. 일부 플랫폼의 경우, 크기는 문제가 더하지, 당신은 (더 적은 공간 차지 다른 데이터 유형을 사용할 수 있습니다 char, short, uint8_t, 등).
내가 이해하기 때문에 1 비트 만 메모리에 점유되지만 부호없는 정수 값 전체는 아닙니다. 맞습니까?
아니요, 정확하지 않습니다. unsigned int비트 중 8 개만 사용하더라도 전체 가 존재합니다.
꽤 좋은 리소스는 C의 Bit Fields입니다 .
기본적인 이유는 사용되는 크기를 줄이는 것입니다. 예를 들어 다음과 같이 작성하는 경우 :
struct {
unsigned int is_keyword;
unsigned int is_extern;
unsigned int is_static;
} flags;
최소 3 * sizeof(unsigned int)또는 12 바이트를 사용하여 3 비트 만 필요로하는 3 개의 작은 플래그를 나타냅니다.
따라서 다음과 같이 작성하면 :
struct {
unsigned int is_keyword : 1;
unsigned int is_extern : 1;
unsigned int is_static : 1;
} flags;
이것은 1과 동일한 공간을 사용 unsigned int하므로 4 바이트입니다. 더 많은 공간이 필요하기 전에 32 개의 1 비트 필드를 구조체에 던질 수 있습니다.
이것은 고전적인 홈 브루 비트 필드와 동일합니다.
#define IS_KEYWORD 0x01
#define IS_EXTERN 0x02
#define IS_STATIC 0x04
unsigned int flags;
그러나 비트 필드 구문은 더 깨끗합니다.
if (flags.is_keyword)
에 맞서:
if (flags & IS_KEYWORD)
오류가 발생하기 쉽습니다.
비트 필드가 일반적인 또 다른 장소는 하드웨어 레지스터입니다. 각 비트가 특정 의미를 갖는 32 비트 레지스터가있는 경우 비트 필드로이를 우아하게 설명 할 수 있습니다.
이러한 비트 필드는 본질적으로 플랫폼에 따라 다릅니다. 이 경우 이식성은 중요하지 않습니다.
우리는 (종종 관련된) 정보의 작은 (종종 2- 상태) 조각을 패킹하려는 바이트 또는 단어 (또는 더 큰 것)와 같은 플래그 구조에 대해 주로 (배타적이지는 않지만) 비트 필드를 사용합니다.
In these scenarios, bit fields are used because they correctly model the problem we're solving: what we're dealing with is not really an 8-bit (or 16-bit or 24-bit or 32-bit) number, but rather a collection of 8 (or 16 or 24 or 32) related, but distinct pieces of information.
비트 필드를 사용하여 해결하는 문제는 정보를 단단히 "패킹"하면 측정 가능한 이점이 있고 / 또는 정보를 "패킹 해제"해도 패널티가없는 문제입니다. 예를 들어 1 바이트에서 8 핀을 노출하고 각 핀의 비트가 보드에 이미 인쇄되어있는 자체 버스를 통과하여 정확히 예상되는 위치로 연결되는 경우 비트 필드가 이상적입니다. 데이터를 "패킹"할 때의 이점은 데이터를 한 번에 전송할 수 있다는 것입니다 (버스의 빈도가 제한되어 있고 작업이 실행 빈도에 의존하는 경우 유용함). 데이터를 "패킹 해제"하면 벌금이 부과됩니다. 존재하지 않음 (또는 존재하지만 가치가 있음).
반면에 일반적인 프로그램 흐름 제어와 같은 다른 경우에는 컴퓨터 아키텍처가 일반적으로 작동하는 방식으로 인해 부울에 비트 필드를 사용하지 않습니다. 대부분의 일반적인 CPU는 메모리에서 1 비트를 가져 오는 것을 좋아하지 않고 바이트 나 정수를 가져 오는 것을 좋아합니다. 또한 비트를 처리하는 것을 좋아하지 않습니다. 명령어는 종종 정수, 단어, 메모리 주소 등과 같은 더 큰 것들에 대해 작동합니다.
따라서 비트에 대해 작업하려고 할 때 비트 마스킹을 수행하고 실제로 원하는 정보를 제외한 모든 구조를 제거하는 추가 작업을 작성하는 것은 사용자 또는 컴파일러 (작성하는 언어에 따라 다름)에 달려 있습니다. 에 운영. 정보를 "패킹"하는 데 이점이없는 경우 (대부분의 경우에는 없습니다) 부울에 비트 필드를 사용하면 코드에 오버 헤드와 노이즈 만 발생합니다.
왜 비트 필드를 사용해야합니까?
바이트 미만으로 저장할 수있는 데이터를 저장하려는 경우 이러한 종류의 데이터는 비트 필드를 사용하여 구조적으로 결합 될 수 있습니다. 임베디드 워드에서 레지스터의 하나의 32 비트 세계가 다른 단어에 대해 다른 의미를 가질 때 비트 파일을 사용하여 더 읽기 쉽게 만들 수 있습니다.
플래그에 비트 필드가 사용되는 것을 발견했습니다. 이제 궁금합니다. 비트 필드가 실제로 사용되는 유일한 방법입니까?
이것이 유일한 방법은 아닙니다. 다른 방법으로도 사용할 수 있습니다.
공간을 절약하기 위해 비트 필드를 사용해야합니까?
예.
내가 이해하기 때문에 1 비트 만 메모리에 점유되지만 부호없는 정수 값 전체는 아닙니다. 맞습니까?
아니. 메모리 만 여러 바이트로만 점유 할 수 있습니다.
원래 질문에 답하기 위해»C에서 비트 필드를 사용할 때?«… Brian Hook의 "Write Portable Code"(ISBN 1-59327-056-9, 독일어 판 ISBN 3-937514-19)에 따르면 -8) 그리고 개인적인 경험 :
C 언어의 비트 필드 관용구를 절대 사용하지 말고 혼자서하십시오.
많은 구현 세부 사항은 컴파일러에 따라 다르며, 특히 공용체와 결합하면 다른 컴파일러와 다른 엔디안에서 보장되지 않습니다. 코드가 이식 가능해야하고 다른 아키텍처 및 / 또는 다른 컴파일러를 사용하여 컴파일 될 가능성이 아주 적다면 사용하지 마십시오.
독점 컴파일러가있는 리틀 엔디안 마이크로 컨트롤러에서 GCC가있는 다른 빅 엔디안 마이크로 컨트롤러로 코드를 이식 할 때이 경우가 있었는데 재미가 없었습니다. :-/
그 이후로 플래그 (호스트 바이트 순서 ;-))를 사용하는 방법입니다.
# define SOME_FLAG (1 << 0)
# define SOME_OTHER_FLAG (1 << 1)
# define AND_ANOTHER_FLAG (1 << 2)
/* test flag */
if ( someint & SOME_FLAG ) {
/* do this */
}
/* set flag */
someint |= SOME_FLAG;
/* clear flag */
someint &= ~SOME_FLAG;
int 유형과 일부 비트 필드 구조체와의 공용체가 필요하지 않습니다. 임베디드 코드를 많이 읽으면 테스트, 설정 및 명확한 패턴이 일반화되고 코드에서 쉽게 발견 할 수 있습니다.
A good usage would be to implement a chunk to translate to-and from-base64 or any unaligned data structure.
struct {
unsigned int e1:6;
unsigned int e2:6;
unsigned int e3:6;
unsigned int e4:6;
} base64enc; //I don't know if declaring a 4-byte array will have the same effect.
struct {
unsigned char d1;
unsigned char d2;
unsigned char d3;
} base64dec;
union base64chunk {
struct base64enc enc;
struct base64dec dec;
};
base64chunk b64c;
//you can assign 3 characters to b64c.enc, and get 4 0-63 codes from b64dec instantly.
This example is a bit naive, since base64 must also consider null-termination (i.e. a string which has not a length l so that l % 3 is 0). But works as a sample of accessing unaligned data structures.
Another example: Using this feature to break a TCP packet header into its components (or other network protocol packet header you want to discuss), althought it is a more advanced and less end-user example. In general: this is useful regarding PC internals, SO, drivers, an encoding systems.
Another example: analyzing a float number.
struct _FP32 {
unsigned int sign:1;
unsigned int exponent:8;
unsigned int mantissa:23;
}
union FP32_t {
_FP32 parts;
float number;
}
(Disclaimer: Don't know the file name / type name where this is applied, but in C this is declared in a header; Don't know how can this be done for 64-bit flaots since the mantissa must have 52bits and -in a 32bit target- ints have 32 bits).
Conclusion: As the concept and these examples show, this is a rarely used feature because it's mostly for internal purposes, and not for day-by-day software.
Bit fields can be used for saving memory space (but using bit field for this purpose is rare). It is used where there is memory constraint. eg) while programming in embedded systems.
But this should be used only if extremely required.
Because we cannot have the address of a bit field. So address operator & cannot be used with them.
You can use them to expand the number of unsigned types that wrap. Ordinary you would have only powers of 8,16,32,64... , but you can have every power with bit-fields.
struct a
{
unsigned int b : 3 ;
} ;
struct a w = { 0 } ;
while( 1 )
{
printf("%u\n" , w.b++ ) ;
getchar() ;
}
To answer the parts of the question no-one else answered:
Ints not Shorts
The reason to use ints rather than shorts etc is that in most cases no space will be saved by doing so.
Modern computers have a 32 or 64 bit architecture and that 32 or 64 bits will be needed even if you use a smaller storage type such as a short.
The smaller types are only useful for saving memory if you can pack them together (for example a short array may use less memory than an int array as the shorts can be packed together tighter in the array). For most cases when using bitfields this is not the case.
Other uses
Bitfields are most commonly used for flags, but there are other things they are used for. For example one way to represent a chess board used in a lot of chess algorithms is to use a 64 bit integer to represent the board (8*8 pixels) and set flags in that integer to give the position of all the white pawns. Another integer shows all the black pawns, etc.
Bit-fields are much more compact and that is an advantage.
But don't forget Packed structures are slower than normal structures. They are also more difficult to construct since the programmer must define the number of bits to use for each field.This is a disadvantage
To utilize the memory space we can use bit fields.
As far as i know in Real world programming if we require we can use booleans instead of declaring it as integers and then making bit field.
If it also is values we use often, not only do we save space, we can also gain peformance since we do not need to pollute the caches. However caching is also the danger in using bit fields since concurrent reads and writes to different bits will cause a data race and updates to completely separate bits might overwrite new values with old values..
Why do we use int? How much space is occupied?
One answer to this question that I haven't seen mentioned in any of the other answers, is that the C standard guarantees support for int. Specifically:
A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation defined type.
It is common for compilers to allow additional bit-field types, but not required. If you're really concerned about portability, int is the best choice.
참고URL : https://stackoverflow.com/questions/24933242/when-to-use-bit-fields-in-c
'Nice programing' 카테고리의 다른 글
| Android : preferences.xml에서 활동 시작 (0) | 2020.11.19 |
|---|---|
| jQuery 확인 (0) | 2020.11.19 |
| SublimeText 3에서 키보드로 열 / 수직 선택 (0) | 2020.11.19 |
| Laravel 5.1에서 Gmail을 사용하여 메일을 보내는 방법은 무엇입니까? (0) | 2020.11.19 |
| 버킷 수준 권한으로 PutObject 작업을 호출 할 때 액세스가 거부 됨 (0) | 2020.11.19 |