UFO ET IT

int8_t 및 uint8_t는 char 유형이 될 예정입니까?

ufoet 2020. 12. 27. 11:48
반응형

int8_t 및 uint8_t는 char 유형이 될 예정입니까?


이 C ++ 11 프로그램이 주어지면 숫자 나 문자가 표시되어야합니까? 아니면 기대하지 않습니까?

#include <cstdint>
#include <iostream>

int main()
{
    int8_t i = 65;
    std::cout << i;
}

표준은이 유형이 문자 유형일 수 있는지 여부를 지정합니까?


C ++ 0x FDIS (N3290)의 § 18.4.1 [cstdint.syn]에서 int8_t다음과 같이 지정되는 선택적 typedef입니다.

namespace std {
  typedef signed integer type int8_t;  // optional
  //...
} // namespace std

§ 3.9.1 [basic.fundamental]은 다음과 같이 설명합니다.

표준 부호있는 정수 유형은 " signed char", " short int", " int", " long int"및 " long long int"의 다섯 가지 입니다. 이 목록에서 각 유형은 목록에있는 이전 유형만큼 최소한의 스토리지를 제공합니다. 구현에서 정의 된 확장 부호있는 정수 유형 도있을 수 있습니다 . 표준 및 확장 부호있는 정수 유형을 집합 적으로 부호있는 정수 유형 이라고 합니다 .

...

유형 bool, char, char16_t, char32_t, wchar_t, 및 서명 및 부호없는 정수 유형의 집합이라고 통합 유형을 . 정수 유형 의 동의어는 정수 유형 입니다.

§ 3.9.1은 또한 다음을 명시합니다.

특정 구현 예에서, 일반 char오브젝트는 하나로서 동일한 값을 취할 수 signed char또는를 unsigned char; 구현에 따라 정의됩니다.

제공된 객체 int8_t의 typedef가 서명 된 값을 취할 있다고 결론을 내리고 싶은 유혹 이 있습니다 . 그러나 이것은 부호있는 정수 유형 (표준 및 확장 부호있는 정수 유형) 목록에없는 경우 가 아닙니다 . 참조 스테판 T. Lavavej의 의견 에를 하고 .charcharcharstd::make_unsignedstd::make_signed

따라서 둘 중 하나 int8_t는의 typedef signed char이거나 객체가 정확히 8 비트 저장소를 차지하는 확장 부호있는 정수 유형입니다.

하지만 질문에 답하기 위해 가정해서는 안됩니다. 두 형태의 기능 때문에 x.operator<<(y)그리고이 operator<<(x,y)정의되어, § 13.5.3는 [over.binary] 우리의 해석을 결정하기 위해 § 13.3.1.2 [over.match.oper]을 참조 말한다 std::cout << i. § 13.3.1.2는 구현이 § 13.3.2 및 § 13.3.3에 따라 후보 기능 집합에서 선택한다고 말합니다. 그런 다음 § 13.3.3.2 [over.ics.rank]를 참조하여 다음을 결정합니다.

  • template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, signed char)템플릿 int8_t은에 대해 정확히 일치 하면 호출됩니다 signed char(예 : typedef of signed char).
  • 그렇지 않으면,이 int8_t승진 될 수 intbasic_ostream<charT,traits>& operator<<(int n)멤버 함수가 호출 될 것이다.

의 경우 std::cout << u에 대한 객체 :uuint8_t

  • template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, unsigned char)템플릿 uint8_t은에 대해 정확히 일치하는 경우 호출됩니다 unsigned char.
  • 이후 그렇지 않으면 int모두 나타낼 수있는 uint8_t값의가 uint8_t로 승격 될 수 intbasic_ostream<charT,traits>& operator<<(int n)멤버 함수가 호출 될 것이다.

항상 문자를 인쇄하려는 경우 가장 안전하고 명확한 옵션은 다음과 같습니다.

std::cout << static_cast<signed char>(i);

항상 숫자를 인쇄하려면 :

std::cout << static_cast<int>(i);

int8_t 정확히 8 비트 너비입니다 (존재하는 경우).

8 비트 수있는 미리 정의 정수 타입은 char, unsigned char, 및 signed char. short둘 다 unsigned short최소 16 비트 여야합니다.

따라서 또는 일반에 int8_t대한 typedef 여야합니다 (플레인 이 서명 된 경우 후자 ).signed charcharchar

int8_t문자가 아닌 정수로 값 을 인쇄하려면 명시 적으로 int.

원칙적으로 C ++ 컴파일러는 8 비트 확장 정수 유형 (예 :라고 함 __int8)을 int8_t정의하고 이에 대한 typedef를 만들 수 있습니다. 내가 그렇게 생각할 수있는 유일한 이유 int8_t는 문자 유형을 만드는 것을 피하는 것 입니다. 실제로이 작업을 수행 한 C ++ 컴파일러를 모릅니다.

int8_t확장 정수 유형은 모두 C99에서 도입되었습니다. C의 경우 char유형을 사용할 수 있을 때 8 비트 확장 정수 유형을 정의 할 특별한 이유 가 없습니다.

업데이트 :

나는이 결론이 완전히 편하지 않다. int8_tuint8_tC99에 소개되었다. C에서 문자 유형인지 여부는 특별히 중요하지 않습니다. 구별이 실제 차이를 만드는 작업은 없습니다. ( putc()표준 C의 최하위 수준 문자 출력 루틴 인조차도 인쇄 할 문자를 int인수 로 취합니다 .) int8_t, 및 uint8_t, 정의 된 경우 거의 확실하게 문자 유형으로 정의되지만 문자 유형은 작은 정수 유형일뿐입니다.

C ++은 특정 오버로드 된 버전 제공 operator<<을위한을 char, signed char그리고 unsigned char그래서, std::cout << 'A'그리고 std::cout << 65매우 다른 결과를 생산하고 있습니다. 나중에, C ++ 채택 int8_t하고 uint8_t있지만, C에서, 그들은 거의 확실 문자 유형이야,하는 방식이다. 대부분의 작업에서 이것은 C에서하는 것보다 더 중요하지 않지만 std::cout << ...다음과 같이 차이가 있습니다.

uint8_t x = 65;
std::cout << x;

아마도 A숫자보다는 문자를 인쇄 할 것입니다 65.

일관된 동작을 원한다면 캐스트를 추가하십시오.

uint8_t x = 65;
std::cout << int(x); // or static_cast<int>(x) if you prefer

문제의 근원은 언어에서 누락 된 것이 있다는 것입니다. 문자 유형이 아닌 매우 좁은 정수 유형입니다.

의도에 관해서 는 위원들이이 문제에 대해 생각하지 않았거나 해결할 가치가 없다고 결정한 것으로 추측 할 수있었습니다. [u]int*_t표준에 유형을 추가하는 이점이 .NET을 사용한 다소 이상한 동작의 불편 함을 능가 한다고 주장 할 수 있습니다 std::cout << ....


질문에 역순으로 답변하겠습니다.

표준은이 유형이 문자 유형일 수 있는지 여부를 지정합니까?

짧은 대답은 : int8_t입니다 signed char가장 인기있는 플랫폼 (Windows의 GCC / 인텔 / 리눅스에 연타 및 Visual Studio)이 아니라 다른 사람에 뭔가 다른 수 있습니다.

긴 대답이 이어집니다.

C ++ 11 표준의 섹션 18.4.1은 <cstdint>다음을 포함하는 시놉시스를 제공합니다.

typedef 부호있는 정수 유형 int8_t; //optional

같은 섹션, 단락 2의 뒷부분에서

헤더 [ <cstdint>]는 C 표준의 7.18과 동일하게 모든 함수, 유형 및 매크로를 정의합니다 .

여기서 C 표준은 1.1 / 2에 따른 C99를 의미합니다.

C ++는 ISO / IEC 9899 : 1999 프로그래밍 언어 — C (이하 C 표준 이라고 함)에 설명 된대로 C 프로그래밍 언어를 기반으로하는 범용 프로그래밍 언어 입니다.

따라서의 정의 int8_t는 C99 표준의 섹션 7.18에서 찾을 수 있습니다. 보다 정확하게는 C99의 섹션 7.18.1.1에 따르면

typedef이름은 intN_t폭 부호있는 정수 유형 지정 N, 아니 패딩 비트 및 2의 보수 표현을. 따라서 int8_t는 너비가 정확히 8 비트 인 부호있는 정수 유형을 나타냅니다 .

또한 C99의 섹션 6.2.5 / 4는

signed char , short int , int , long intlong long int 로 지정된 다섯 가지 표준 부호있는 정수 유형이 있습니다 . (이러한 유형 및 기타 유형은 6.7.2에 설명 된대로 여러 가지 추가 방식으로 지정 될 수 있습니다.) 구현 정의 확장 부호있는 정수 유형 도있을 수 있습니다 . 표준 및 유형 정수 서명 확장 된 일괄 유형 부호있는 정수라고한다 .

마지막으로 C99의 섹션 5.2.4.2.1은 표준 부호있는 정수 유형에 대해 최소 크기를 부과합니다. 를 제외 signed char하고 나머지는 모두 16 비트 이상입니다.

따라서, int8_t어느 하나 인 signed char또는 8 비트 길이 (비표준) 부호 정수형 확장.

Both glibc (the GNU C library) and Visual Studio C library define int8_t as signed char. Intel and Clang, at least on Linux, also use libc and hence, the same applies to them. Therefore, in the most popular platforms int8_t is signed char.

Given this C++11 program, should I expect to see a number or a letter? Or not make expectations?

Short answer: In the most popular platforms (GCC/Intel/Clang on Linux and Visual Studio on Windows) you will certainly see the letter 'A'. In other platforms you might get see 65 though. (Thanks to DyP for pointing this out to me.)

In the sequel, all references are to the C++11 standard (current draft, N3485).

Section 27.4.1 provides the synopsis of <iostream>, in particular, it states the declaration of cout:

extern ostream cout;

Now, ostream is a typedef for a template specialization of basic_ostream as per Section 27.7.1:

template <class charT, class traits = char_traits<charT> >
class basic_ostream;

typedef basic_ostream<char> ostream;

Section 27.7.3.6.4 provides the following declaration:

template<class traits>
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, signed char c);

If int8_t is signed char then it's this overload that's going to be called. The same section also specifies that the effect of this call is printing the character (not the number).

Now, let's consider the case where int8_t is an extended signed integer type. Obviously, the standard doesn't specify overloads of operator<<() for non standard types but thanks to promotions and convertions one of the provided overloads might accept the call. Indeed, int is at least 16 bits long and can represent all the values of int8_t. Then 4.5/1 gives that int8_t can be promoted to int. On the other hand, 4.7/1 and 4.7/2 gives that int8_t can be converted to signed char. Finally, 13.3.3.1.1 yields that promotion is favored over convertion during overload resolution. Therefore, the following overload (declared in in 23.7.3.1)

basic_ostream& basic_ostream::operator<<(int n);

will be called. This means that, this code

int8_t i = 65;
std::cout << i;

will print 65.

Update:

1. Corrected the post following DyP's comment.

2. Added the following comments on the possibility of int8_t be a typedef for char.

As said, the C99 standard (Section 6.2.5/4 quoted above) defines 5 standard signed integer types (char is not one of them) and allows implementations to add their onw which are referred as non standard signed integer types. The C++ standard reinforces that definition in Section 3.9.1/2:

There are five standard signed integer types : “signed char”, “short int”, “int”, “long int”, and “long long int” [...] There may also be implementation-defined extended signed integer types. The standard and extended signed integer types are collectively called signed integer types.

Later, in the same section, paragraph 7 says:

Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types. A synonym for integral type is integer type.

Therefore, char is an integer type but char is neither a signed integer type nor an unsigned integer type and Section 18.4.1 (quoted above) says that int8_t, when present, is a typedef for a signed integer type.

What might be confusing is that, depending on the implementation, char can take the same values as a signed char. In particular, char might have a sign but it's still not a signed char. This is explicitly said in Section 3.9.1/1:

[...] Plain char, signed char, and unsigned char are three distinct types. [...] In any particular implementation, a plain char object can take on either the same values as a signed char or an unsigned char; which one is implementation-defined.

This also implies that char is not a signed integer type as defined by 3.9.1/2.

3. I admit that my interpretation and, specifically, the sentence "char is neither a signed integer type nor an unsigned integer type" is a bit controversial.

To strength my case, I would like to add that Stephan T. Lavavej said the very same thing here and Johannes Schaub - litb also used the same sentence in a comment on this post.


The working draft copy I have, N3376, specifies in [cstdint.syn] § 18.4.1 that the int types are typically typedefs.

namespace std {
typedef signed integer type int8_t; // optional
typedef signed integer type int16_t; // optional
typedef signed integer type int32_t; // optional
typedef signed integer type int64_t; // optional
typedef signed integer type int_fast8_t;
typedef signed integer type int_fast16_t;
typedef signed integer type int_fast32_t;
typedef signed integer type int_fast64_t;
typedef signed integer type int_least8_t;
typedef signed integer type int_least16_t;
typedef signed integer type int_least32_t;
typedef signed integer type int_least64_t;
typedef signed integer type intmax_t;
typedef signed integer type intptr_t; // optional
typedef unsigned integer type uint8_t; // optional
typedef unsigned integer type uint16_t; // optional
typedef unsigned integer type uint32_t; // optional
typedef unsigned integer type uint64_t; // optional
typedef unsigned integer type uint_fast8_t;
typedef unsigned integer type uint_fast16_t;
typedef unsigned integer type uint_fast32_t;
typedef unsigned integer type uint_fast64_t;
typedef unsigned integer type uint_least8_t;
typedef unsigned integer type uint_least16_t;
typedef unsigned integer type uint_least32_t;
typedef unsigned integer type uint_least64_t;
typedef unsigned integer type uintmax_t;
typedef unsigned integer type uintptr_t; // optional
} // namespace std

Since the only requirement made is that it must be 8 bits, then typedef to a char is acceptable.


char/signed char/unsigned char are three different types, and a char is not always 8 bits. on most platform they are all 8-bits integer, but std::ostream only defined char version of >> for behaviors like scanf("%c", ...).

ReferenceURL : https://stackoverflow.com/questions/15911714/are-int8-t-and-uint8-t-intended-to-be-char-types

반응형