program story

바이트 버퍼는 부호가있는 또는 부호없는 문자 버퍼 여야합니까?

inputbox 2021. 1. 11. 08:06
반응형

바이트 버퍼는 부호가있는 또는 부호없는 문자 버퍼 여야합니까?


바이트 버퍼는 부호있는 문자 또는 부호없는 문자 또는 단순히 문자 버퍼 여야합니까? C와 C ++의 차이점은 무엇입니까?

감사.


바이트 버퍼는 부호있는 문자 또는 부호없는 문자 또는 단순히 문자 버퍼 여야합니까? C와 C ++의 차이점은 무엇입니까?

언어가 처리하는 방식에 약간의 차이가 있습니다. 거대한 방법 컨벤션 취급 그것의 차이.

  • char= ASCII (또는 UTF-8이지만 서명이 방해가 됨) 텍스트 데이터
  • unsigned char = 바이트
  • signed char = 거의 사용되지 않음

그리고 그러한 구별에 의존 하는 코드가 있습니다. 1 ~ 2 주 전에 JPEG 데이터가 char*"문자열"의 모든 유효하지 않은 UTF-8을 "유용하게"대체하는 Base64 인코딩 기능 버전 으로 전달 되었기 때문에 손상되는 버그가 발생했습니다 . BYTE일명 unsigned char으로 변경하면 문제를 해결할 수있었습니다.


임의의 이진 데이터를 저장하려면 unsigned char. C 표준에 의해 패딩 비트가 없음을 보장하는 유일한 데이터 유형입니다. 서로 다른 데이터 유형은 객체 표현에 패딩 비트를 포함 할 수 있습니다 (즉, 값을 결정하는 비트 만이 아니라 객체의 모든 비트를 포함하는 비트). 패딩 비트의 상태는 지정되지 않으며 값을 저장하는 데 사용되지 않습니다. 따라서 char일부 이진 데이터를 사용하여 읽으면 (값 비트 만 해석하여) 문자의 값 범위로 축소되지만 무시되지만 여전히 존재하고에서 읽는 비트가있을 수 있습니다 memcpy. 실제 구조체 객체의 패딩 비트와 매우 유사합니다. 유형 unsigned char은 그것들을 포함하지 않는 것을 보장합니다. 이는 5.2.4.2.1/2(C99 TC2, n1124 여기)에서 이어집니다.

char 유형의 객체 값이 표현식에서 사용될 때 부호있는 정수로 취급되는 경우의 값은의 값과 CHAR_MIN동일해야하며 SCHAR_MIN의 값은의 값과 CHAR_MAX동일해야합니다 SCHAR_MAX. 그렇지 않으면의 값은 CHAR_MIN0이고의 값은의 값과 CHAR_MAX동일합니다 UCHAR_MAX. 값은 UCHAR_MAX동일해야합니다.2^CHAR_BIT − 1

마지막 문장에서 패딩 비트를위한 공간이 남아 있지 않음을 알 수 있습니다. char버퍼의 유형으로 사용 하는 경우 오버플로 문제도 있습니다. 8비트 범위에있는 이러한 요소 중 하나에 명시 적으로 값을 할당하면 해당 할당이 정상일 것으로 예상 할 수 있지만 범위 내에 있지는 않습니다. a char, 즉 CHAR_MIN.. CHAR_MAX, 이러한 변환은 오버플로되고 신호 발생을 포함한 구현 정의 결과를 유발합니다.

위와 관련된 문제가 실제 구현에서 나타나지 않더라도 (구현의 품질이 매우 낮을 수 있음 ) 처음부터 올바른 유형을 사용하는 것이 가장 좋습니다 unsigned char.

그러나 문자열의 경우 선택한 데이터 유형은 char이며 문자열 및 인쇄 함수로 이해됩니다. signed char이러한 목적으로 사용 하는 것은 나에게 잘못된 결정처럼 보입니다.

자세한 내용 this proposal은 결국 signed char패딩 비트도 필요로 하지 않는 다음 버전의 C 표준에 대한 수정 사항이 포함 된 내용을 읽어보십시오 . 이미 작업 문서에 포함되어 있습니다.


때에 따라 다르지.

버퍼가 텍스트를 보유하도록 의도 된 경우,이를 배열로 선언 char하고 플랫폼이 기본적으로 서명되었는지 여부를 결정하도록하는 것이 좋습니다. 예를 들어 구현의 런타임 라이브러리 안팎으로 데이터를 전달하는 데 문제가 거의 없습니다.

버퍼가 이진 데이터를 보유하도록 의도 된 경우 사용하려는 방법에 따라 다릅니다. 예를 들어, 이진 데이터가 실제로 서명 된 8 비트 고정 소수점 ADC 측정 인 데이터 샘플의 패킹 된 배열 인 signed char경우 가장 좋습니다.

대부분의 실제 상황에서 버퍼는 그저 버퍼입니다. 대량 작업에서 버퍼를 채웠고이를 a 구문 분석기를 사용하여 복잡한 데이터 구조를 해석하고 유용한 작업을 수행합니다. 이 경우 가장 간단한 방법으로 선언하십시오.


시스템의 기본 로케일의 문자열이 아니라 실제로 8 비트 바이트의 버퍼 인 경우 uint8_t. 문자가 바이트 (또는 바이트가 옥텟)가 아닌 주변에 많은 기계가있는 것은 아니지만, '이것은 문자열'이 아니라 '이것은 옥텟의 버퍼입니다'라는 문장을 만드는 것은 종종 유용한 문서입니다.


char 또는 unsigned char 중 하나를 사용해야 하지만 서명 되지 않은 char . 표준은 3.9 / 2에서 다음과 같습니다.

POD 유형 T의 모든 개체 (기본 클래스 하위 개체 제외)의 경우 개체가 T 유형의 유효한 값을 보유하는지 여부에 관계없이 개체를 구성하는 기본 바이트 (1.7)는 char 또는 unsigned 배열로 복사 될 수 있습니다. char. char 또는 unsigned char 배열의 내용이 객체로 다시 복사되면 객체는 이후에 원래 값을 유지합니다.


unsigned char로 정의하는 것이 좋습니다. 사실 Win32 유형 BYTE는 unsigned char로 정의됩니다. 이것 사이에 C와 C ++ 사이에는 차이가 없습니다.


최대 이식성을 위해 항상 unsigned char를 사용하십시오. 이것이 작동 할 수있는 몇 가지 경우가 있습니다. 엔디안 유형이 다른 시스템간에 공유되는 직렬화 된 데이터가 즉시 떠 오릅니다. 시프트 또는 비트 마스킹을 수행 할 때 값은 다른 것입니다.


int8_t 대 uint8_t의 선택은 ptr을 NULL로 비교할 때와 유사합니다.


기능적 관점에서 NULL은 0에 대한 #define이므로 NULL과 비교하는 것은 0과 비교하는 것과 동일합니다.

그러나 개인적으로 코딩 스타일 관점에서 NULL #define은 잘못된 포인터를 확인하는 코드를 유지 관리하는 사람을 의미하기 때문에 내 포인터를 NULL과 비교하기로 선택합니다.

VS

누군가 0과의 비교를 보면 특정 값을 확인하고 있음을 의미합니다.


위의 이유로 uint8_t를 사용합니다.


요소를 더 넓은 변수로 가져 오면 물론 부호 확장 여부가 결정됩니다.


해야 할 일과해야 할 일 ... 저는 서명되지 않은 것을 선호하는 경향 ints이 있습니다. 데이터의 이진성을 강조하고 싶다면 "원시적"이라고 느끼고 "이건 작은 무리입니다"라고 말하고 싶지 않기 때문 입니다.

나는 signed char바이트 버퍼를 표현 하기 위해 명시 적을 사용한 적이 없다고 생각한다 .

물론, 1/3 옵션은 void *가능한 한 버퍼를 표현하는 것입니다. 많은 공통 I / O 함수가에서 작동 void *하므로 사용할 정수 유형을 완전히 캡슐화 할 수 있습니다.


몇 년 전에 나는 128 이상의 ASCII 값에 대해 컬러 문자를 인쇄하는 C ++ 콘솔 응용 프로그램에 문제가 있었는데 이것은 char에서 unsigned char로 전환하여 해결되었지만 char 유형을 유지하면서 해결할 수 있었다고 생각합니다.

For now, most C/C++ functions use char and I understand both languages much better now, so I use char in most cases.


Do you really care? If you don't, just use the default (char) and don't clutter your code with unimportant matter. Otherwise, future maintainers will be left wondering why did you use signed (or unsigned). Make their life simpler.


If you lie to the compiler, it will punish you.

If the buffer contains data that is just passing through, and you will not manipulate them in any way, it doesn't matter.

However, if you have to operate on the buffer contents then the correct type declaration will make your code simpler. No "int val = buf[i] & 0xff;" nonsense.

So, think about what the data actually is and how you need to use it.


typedef char byte;

Now you can make your array be of bytes. It's obvious to everyone what you meant, and you don't lose any functionality.

I know it's somewhat silly, but it makes your code read 100% as you intended.

ReferenceURL : https://stackoverflow.com/questions/653336/should-a-buffer-of-bytes-be-signed-or-unsigned-char-buffer

반응형