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의 의견 에를 하고 .char
char
char
std::make_unsigned
std::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 ofsigned char
). - 그렇지 않으면,이
int8_t
승진 될 수int
와basic_ostream<charT,traits>& operator<<(int n)
멤버 함수가 호출 될 것이다.
의 경우 std::cout << u
에 대한 객체 :u
uint8_t
- 이
template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, unsigned char)
템플릿uint8_t
은에 대해 정확히 일치하는 경우 호출됩니다unsigned char
. - 이후 그렇지 않으면
int
모두 나타낼 수있는uint8_t
값의가uint8_t
로 승격 될 수int
와basic_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 char
char
char
int8_t
문자가 아닌 정수로 값 을 인쇄하려면 명시 적으로 int
.
원칙적으로 C ++ 컴파일러는 8 비트 확장 정수 유형 (예 :라고 함 __int8
)을 int8_t
정의하고 이에 대한 typedef를 만들 수 있습니다. 내가 그렇게 생각할 수있는 유일한 이유 int8_t
는 문자 유형을 만드는 것을 피하는 것 입니다. 실제로이 작업을 수행 한 C ++ 컴파일러를 모릅니다.
int8_t
확장 정수 유형은 모두 C99에서 도입되었습니다. C의 경우 char
유형을 사용할 수 있을 때 8 비트 확장 정수 유형을 정의 할 특별한 이유 가 없습니다.
업데이트 :
나는이 결론이 완전히 편하지 않다. int8_t
및 uint8_t
C99에 소개되었다. 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 int 및 long 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
, andunsigned char
are three distinct types. [...] In any particular implementation, a plainchar
object can take on either the same values as asigned char
or anunsigned 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
'your programing' 카테고리의 다른 글
OpenID 식별자 및 OAuth 토큰을 안전하게 저장 (0) | 2020.12.25 |
---|---|
AMQP와 같은 메시지 지향 미들웨어는 어떤 도메인에서 유용합니까? (0) | 2020.12.25 |
node.js가 공유 호스팅에서 실행되지 않는 이유는 무엇입니까? (0) | 2020.12.25 |
Visual Studio 2017 프로젝트에서 C # 7의 모든 기능을 활성화하려면 어떻게해야합니까? (0) | 2020.12.25 |
Windows XP에서 Eclipse의 내부 브라우저를 IE에서 Firefox로 변경하려면 어떻게해야합니까? (0) | 2020.12.25 |