uint8_t vs 부호없는 char


231

C에서 uint8_tover 를 사용하면 어떤 이점이 unsigned char있습니까?

거의 모든 시스템 uint8_t에서에 대한 typedef 라는 것을 알고 있습니다. unsigned char왜 사용합니까?

답변:


225

그것은 당신의 의도를 문서화합니다-당신은 문자가 아닌 작은 숫자를 저장할 것입니다.

당신이 같은 다른 형식 정의를 사용하는 경우 또한 그것은 더 좋은 모습 uint16_t또는 int32_t.


1
우리가 표준 유형에 대해 이야기하고 있는지 여부는 원래 질문에서 명확하지 않았습니다. 수년에 걸쳐이 명명 규칙에 많은 변형이 있었을 것입니다.
Mark Ransom

8
의도하지 않은 것이 문자로 작업하고 있음을 나타 내기 때문에 의도를 명시 적으로 사용 unsigned char하거나 signed char문서화합니다 char.
caf

9
나는 정의 되지 않은 unsigned것이 unsigned int정의 에 의한 것이라고 생각 했습니까?
Mark Ransom

5
@endolith, 문자열에 uint8_t를 사용하는 것이 반드시 틀린 것은 아니지만 분명히 이상합니다.
마크 랜섬

5
@endolith, UTF8 텍스트로 uint8_t에 대한 사례를 만들 수 있다고 생각합니다. 실제로, char문자를 암시하는 것처럼 보이지만 UTF8 문자열과 관련하여 멀티 바이트 문자의 1 바이트 일 수 있습니다. uint8_t를 사용하면 모든 위치에서 문자를 기 대해서는 안됩니다. 즉, 문자열 / 배열의 각 요소는 의미 론적 가정을해서는 안되는 임의의 정수입니다. 물론 모든 C 프로그래머는 이것을 알고 있지만 초보자에게 올바른 질문을 할 수 있습니다.
tne

70

간단한 시스템이기 때문에 일부 시스템에는 8 비트 유형이 없을 수 있습니다. Wikipedia 에 따르면 :

요구 사항을 충족하는 유형이있는 경우에만 N = 8, 16, 32 또는 64에 대해 정확한 너비 정수 유형을 정의하려면 구현이 필요합니다. 적절한 유형을 지원하더라도 다른 N에 대해서는 정의 할 필요가 없습니다.

그래서 uint8_t8 비트 = 1 바이트 모든 플랫폼는 것이지만, 존재하지 않을 수 있습니다. 일부 임베디드 플랫폼은 다를 수 있지만 매우 드물어지고 있습니다. 일부 시스템은 char유형을 16 비트로 정의 할 수 있으며,이 경우 8 비트 유형이 아닐 수 있습니다.

그 (사소한) 문제 외에 @Mark Ransom의 대답 은 내 의견으로는 최고입니다. 데이터를 가장 잘 보여주는 것을 사용하십시오.

또한 uint8_t(표준의 일부 stdint.h가 아닌) uint_8( 헤더에 제공된 C99의 표준 typedef) 를 의미한다고 가정합니다 .


3
호기심이 많은 @caf-일부 설명에 연결할 수 있습니까? 누군가가 comp.lang.c ++. mode에서 C / C ++ 형식 보장이 너무 약한 지 여부에 대한 토론에서 언급 한 (그리고 개발자 문서에 링크되어 있기 때문에) 존재한다는 것을 알고 있지만 더 이상 해당 스레드를 찾을 수 없으며 항상 편리합니다. 비슷한 토론에서 그것을 참조하기 위해 :)
Pavel Minaev

3
"일부 시스템에서는 문자 유형을 16 비트로 정의 할 수 있으며,이 경우 8 비트 유형이 없을 수 있습니다." -나에게서 약간의 잘못된 반대에도 불구하고 Pavel은 char이 16 비트이면 컴파일러가 8 비트 유형을 제공하더라도 호출 하지 않아야uint8_t 한다는 것을 입증 했습니다 (또는 typedef로). 이것은 8 비트 타입이 스토리지 표현에서 사용되지 않는 비트를 uint8_t가지기 때문입니다.
Steve Jessop

3
SHARC 아키텍처에는 32 비트 단어가 있습니다. 자세한 내용은 en.wikipedia.org/wiki/… 를 참조하십시오.
BCran

2
TI의 C5000 DSP (OMAP1 및 OMAP2에 있음)는 16 비트입니다. OMAP3의 경우 8 비트 문자를 사용하여 C6000 시리즈로 갔다고 생각합니다.
Steve Jessop

4
N3242에 파기- "프로그래밍 언어 C ++의 표준 작업 초안", 섹션 18.4.1 <cstdint> 시놉시스의 말- typedef unsigned integer type uint8_t; // optional 본질적으로 C ++ 표준 준수 라이브러리는 uint8_t를 전혀 정의 할 필요가 없습니다 (// 선택 주석 참조) )
nightlytrails 2013

43

요점은 구현 독립적 인 코드를 작성하는 것입니다. unsigned char8 비트 유형일 수는 없습니다. uint8_t입니다 (사용 가능한 경우).


4
... 시스템에 존재하지만 매우 드 rare니다. 한
크리스 루츠

2
uint8_t가 없기 때문에 시스템에서 코드를 컴파일하지 못하는 데 실제로 문제가 발생하면 find 및 sed를 사용하여 uint8_t의 모든 발생을 서명되지 않은 char 또는 더 유용한 것으로 자동으로 변경할 수 있습니다.
bazz

2
@bazz-8 비트 유형이라고 가정하지 않으면 원격 시스템에서 바이트 단위로 패키지 된 데이터를 압축 해제하는 것과 같이 할 수 없습니다. 암시적인 가정은 uint8_t가 존재하지 않는 이유는 char이 8 비트를 초과하는 프로세서에 있기 때문입니다.
Chris Stratton

주장 단언에 던져 assert (sizeof (unsigned char) == 8);
bazz

3
@bazz 잘못된 주장 나는 두렵다. 1 바이트 sizeof(unsigned char)를 반환 1합니다. 그러나 시스템 char와 int의 크기가 예를 들어 16 비트와 같은 경우 다음 sizeof(int)도 반환됩니다.1
Toby

7

당신이 말했듯이, " 거의 모든 시스템".

char아마 변경 가능성이 적지 만, 일단 uint16_t친구와 친구를 사용하기 시작 하면 uint8_t블렌드를 더 잘 사용 하고 코딩 표준의 일부일 수도 있습니다.


7

내 경험상 uint8_t를 사용하여 8 비트 (및 uint16_t 등)를 사용하고 8 비트보다 작은 필드를 가질 수있는 두 곳이 있습니다. 두 곳 모두 공간이 중요한 곳이므로 디버깅 할 때 데이터의 원시 덤프를 살펴보고 해당 데이터가 나타내는 내용을 신속하게 확인할 수 있어야합니다.

첫 번째는 RF 프로토콜, 특히 협 대역 시스템에 있습니다. 이 환경에서는 최대한 많은 정보를 단일 메시지에 담아 야합니다. 두 번째는 공간이 매우 제한된 플래시 스토리지 (예 : 임베디드 시스템)입니다. 두 경우 모두 컴파일러가 압축 및 압축 풀기를 처리하는 압축 된 데이터 구조를 사용할 수 있습니다.

#pragma pack(1)
typedef struct {
  uint8_t    flag1:1;
  uint8_t    flag2:1;
  padding1   reserved:6;  /* not necessary but makes this struct more readable */
  uint32_t   sequence_no;
  uint8_t    data[8];
  uint32_t   crc32;
} s_mypacket __attribute__((packed));
#pragma pack()

사용하는 방법은 컴파일러에 따라 다릅니다. 동일한 헤더 파일로 여러 다른 컴파일러를 지원해야 할 수도 있습니다. 이것은 장치와 서버가 완전히 다를 수있는 임베디드 시스템에서 발생합니다. 예를 들어 x86 Linux 서버와 통신하는 ARM 장치가있을 수 있습니다.

패킹 된 구조를 사용하는 경우 몇 가지주의 사항이 있습니다. 가장 큰 문제는 회원의 주소를 역 참조하지 않아야한다는 것입니다. 뮤티 바이트로 정렬 된 단어가있는 시스템에서 이로 인해 예외가 잘못 정렬되고 코어 덤프가 발생할 수 있습니다.

일부 사람들은 성능에 대해 걱정하고 이러한 압축 구조를 사용하면 시스템 속도가 느려질 것이라고 주장합니다. 배후에서 컴파일러가 정렬되지 않은 데이터 멤버에 액세스하는 코드를 추가하는 것은 사실입니다. IDE에서 어셈블리 코드를 보면 알 수 있습니다.

그러나 패킹 된 구조는 통신 및 데이터 저장에 가장 유용하므로 메모리에서 작업 할 때 데이터를 패킹되지 않은 표현으로 추출 할 수 있습니다. 일반적으로 메모리의 전체 데이터 패킷으로 작업 할 필요는 없습니다.

다음은 관련 토론입니다.

pragma pack (1) 또는 __attribute__ ((aligned (1))) 작동

gcc의 __attribute __ ((packed)) / #pragma pack이 안전하지 않습니까?

http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html


6

거의 없습니다. 이식성 관점에서, char8 비트보다 작을 수 없으며 , 보다 작을 수 없습니다 char. 따라서 주어진 C 구현에 부호없는 8 비트 정수 유형이있는 경우에는 char입니다. 대안으로, 전혀 속하지 않을 수도 있습니다 typedef.

8 비트 바이트가 필요하고 다른 것은 필요 없다는 것이 분명하다는 의미에서 코드를 더 잘 문서화하는 데 사용할 수 있습니다. 그러나 실제로 실제로 거의 모든 곳에서 합리적인 기대치입니다 (사실이 아닌 DSP 플랫폼이 있지만 코드가 실행될 가능성은 적으며 프로그램 상단의 정적 어설 션을 사용하면 오류가 발생할 수 있습니다) 그러한 플랫폼).


7
@Skizz-아니요, 표준은 unsigned char0에서 255 사이의 값을 보유 할 수 있어야합니다. 4 비트로이를 수행 할 수 있으면 내 모자가 사라집니다.
크리스 루츠

1
"조금 더 성가시다"-컴파일러 작성자가있는 곳까지 걸어 가야한다고 생각하는 것은 번거 롭다. uint8_t구현에 추가 하도록합니다. 16 비트 문자가있는 DSP의 컴파일러가 일반적으로 구현되는지 아닌지 궁금합니다 uint8_t.
Steve Jessop

6
그건 그렇고, 두 번째 생각에, 아마도 "나는 정말로 8 비트가 필요하다"라고 말하는 가장 간단한 방법 #include <stdint.h>일 것 uint8_t입니다. 플랫폼에 있으면 플랫폼이 제공합니다. 플랫폼에없는 경우 프로그램은 컴파일되지 않으며 이유는 명확하고 간단합니다.
Pavel Minaev

2
여전히 시가는 없습니다. "부인되지 않은 char 이외의 부호없는 정수 유형의 경우 객체 표현의 비트는 값 비트와 패딩 비트의 두 그룹으로 나뉩니다. N 값 비트가있는 경우 각 비트는 서로 다릅니다. 1과 2 ^ (N-1) 사이의 2의 거듭 제곱으로, 해당 유형의 오브젝트는 순수한 2 진 표현을 사용하여 0에서 2 ^ (N-1)까지의 값을 표시 할 수 있어야합니다. typedef 이름 intN_t는 너비 N, 패딩 비트 없음 및 2의 보수 표현 을 갖는 부호있는 정수 유형 . "
Pavel Minaev

1
산술 모듈로만 필요한 경우 부호없는 비트 필드는 제대로 작동합니다 (불편한 경우). 예를 들어, 패딩이없는 8 진수 배열이 필요할 때입니다. 바로 SOL입니다. 이야기의 교훈은 : 적절한 정직 - 투 - 하나님의 8 비트 문자 아키텍처에 DSP를위한 코드 및 스틱하지 않습니다
파벨 Minaev

4

예를 들어 네트워크 분석기를 작성할 때 매우 중요합니다. 패킷 헤더는 특정 플랫폼의 C 컴파일러가 작동하는 방식이 아니라 프로토콜 사양에 의해 정의됩니다.


내가 이것을 물었을 때 나는 시리얼을 통한 통신을위한 간단한 프로토콜을 정의했다.
Lyndon White

2

거의 모든 시스템에서 uint8_t == unsigned char을 만났지만 C 표준에서는 보장하지 않습니다. 이식 가능한 코드를 작성하려고하는데 메모리 크기가 정확히 중요한 경우 uint8_t를 사용하십시오. 그렇지 않으면 부호없는 문자를 사용하십시오.


3
uint8_t 8 비트 인 unsigned char경우 항상 범위와 크기 및 패딩 (없음)과 일치합니다 unsigned char. 때 unsigned char8 비트가 아닌, uint8_t존재하지 않습니다.
chux-Reinstate Monica

@ chux, 표준의 정확한 위치에 대한 참조가 있습니까? unsigned char8 비트 인 경우 , 확장 된 부호없는 정수형이 아닌 그것의 것이 uint8_t보장 됩니까? typedeftypedef
hsivonen

@hsivonen "표준에서 정확한 위치는?" -> 아니오 – 아직 7.20.1.1을보십시오. unsigned char/signed char/char가장 작은 유형 인 8 비트 이상 으로 쉽게 추론됩니다 . unsigned char패딩이 없습니다. 그러기 uint8_t위해서는 구현이 제공 한 정수 유형 :의 최소 요구 사항과 일치하므로 패딩이없는 8 비트 여야합니다 unsigned char. "... typedef가 보장된다 ..."에 관해서는 게시하기 좋은 질문처럼 보입니다.
chux-Reinstate Monica
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.