C++ int8_t 和 uint8_t 是 char 类型吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15911714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are int8_t and uint8_t intended to be char types?
提问by Drew Dormann
Given this C++11 program, should I expect to see a number or a letter? Or not make expectations?
鉴于这个 C++11 程序,我应该期望看到一个数字还是一个字母?还是不做期望?
#include <cstdint>
#include <iostream>
int main()
{
int8_t i = 65;
std::cout << i;
}
Does the standard specify whether this type can or will be a character type?
标准是否指定此类型是否可以或将是字符类型?
采纳答案by Daniel Trebbien
From § 18.4.1 [cstdint.syn] of the C++0x FDIS (N3290), int8_t
is an optional typedef that is specified as follows:
来自 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] states:
§ 3.9.1 [basic.fundamental] 指出:
There are five standard signed integer types: “
signed char
”, “short int
”, “int
”, “long int
”, and “long long int
”. In this list, each type provides at least as much storage as those preceding it in the list. There may also be implementation-defined extended signed integer types. The standard and extended signed integer types are collectively called signed integer types....
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.
有五种标准的有符号整数类型:“
signed char
”、“short int
”、“int
”、“long int
”和“long long int
”。在此列表中,每种类型至少提供与列表中它之前的类型一样多的存储空间。也可能有实现定义的扩展有符号整数类型。标准的和扩展的有符号整数类型统称为有符号整数类型。...
类型
bool
,char
,char16_t
,char32_t
,wchar_t
以及有符号和无符号整数类型统称为整型。整数类型的同义词是整数类型。
§ 3.9.1 also states:
§ 3.9.1 还指出:
In any particular implementation, a plain
char
object can take on either the same values as asigned char
or anunsigned char
; which one is implementation-defined.
在任何特定的实现中,普通
char
对象可以采用与 asigned char
或 an相同的值unsigned char
;哪个是实现定义的。
It is tempting to conclude that int8_t
may be a typedef of char
provided char
objects take on signed values; however, this is not the case as char
is not among the list of signed integer types(standard and possibly extended signed integer types). See also Stephan T. Lavavej's commentson std::make_unsigned
and std::make_signed
.
很容易得出结论,int8_t
所char
提供char
对象的 typedef 可能采用有符号值;然而,情况并非如此,因为char
它不在有符号整数类型列表(标准和可能扩展的有符号整数类型)中。另请参阅Stephan T. Lavavej对std::make_unsigned
和的评论std::make_signed
。
Therefore, either int8_t
is a typedef of signed char
or it is an extended signed integer type whose objects occupy exactly 8 bits of storage.
因此,要么int8_t
是 typedef要么是signed char
扩展的有符号整数类型,其对象正好占用 8 位存储空间。
To answer your question, though, you should not make assumptions. Because functions of both forms x.operator<<(y)
and operator<<(x,y)
have been defined, § 13.5.3 [over.binary] says that we refer to § 13.3.1.2 [over.match.oper] to determine the interpretation of std::cout << i
. § 13.3.1.2 in turn says that the implementation selects from the set of candidate functions according to § 13.3.2 and § 13.3.3. We then look to § 13.3.3.2 [over.ics.rank] to determine that:
但是,要回答您的问题,您不应该做出假设。因为两种形式的函数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] 来确定:
- The
template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, signed char)
template would be called ifint8_t
is an Exact Match forsigned char
(i.e. a typedef ofsigned char
). - Otherwise, the
int8_t
would be promoted toint
and thebasic_ostream<charT,traits>& operator<<(int n)
member function would be called.
- 该
template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, signed char)
模板会,如果被称为int8_t
是一个精确匹配signed char
(即的一个typedefsigned char
)。 - 否则,
int8_t
将提升为int
并basic_ostream<charT,traits>& operator<<(int n)
调用成员函数。
In the case of std::cout << u
for u
a uint8_t
object:
在的情况下std::cout << u
为u
一个uint8_t
对象:
- The
template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&, unsigned char)
template would be called ifuint8_t
is an Exact Match forunsigned char
. - Otherwise, since
int
can represent alluint8_t
values, theuint8_t
would be promoted toint
and thebasic_ostream<charT,traits>& operator<<(int n)
member function would be called.
- 该
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)
调用成员函数。
If you always want to print a character, the safest and most clear option is:
如果你总是想打印一个字符,最安全和最明确的选择是:
std::cout << static_cast<signed char>(i);
And if you always want to print a number:
如果你总是想打印一个数字:
std::cout << static_cast<int>(i);
回答by Keith Thompson
int8_t
is exactly 8 bits wide (if it exists).
int8_t
正好是 8 位宽(如果存在)。
The only predefined integer types that can be 8 bits are char
, unsigned char
, and signed char
. Both short
and unsigned short
are required to be at least 16 bits.
唯一预定义整数类型,可以是8位是char
,unsigned char
,和signed char
。二者short
并unsigned short
需要是至少16位。
So int8_t
must be a typedef for either signed char
or plain char
(the latter if plain char
is signed).
所以int8_t
必须是一个 typedef 或者是signed char
plain char
(如果plainchar
是签名的,则后者)。
If you want to print an int8_t
value as an integer rather than as a character, you can explicitly convert it to int
.
如果要将int8_t
值打印为整数而不是字符,则可以将其显式转换为int
.
In principle, a C++ compiler could define an 8-bit extended integer type(perhaps called something like __int8
), and make int8_t
a typedef for it. The only reason I can think of to do so would be to avoid making int8_t
a character type. I don't know of any C++ compilers that have actually done this.
原则上,C++ 编译器可以定义一个 8 位扩展整数类型(可能称为类似__int8
),并int8_t
为其创建typedef。我能想到的唯一原因是避免创建int8_t
字符类型。我不知道有任何 C++ 编译器真正做到了这一点。
Both int8_t
and extended integer types were introduced in C99. For C, there's no particular reason to define an 8-bit extended integer type when the char
types are available.
无论int8_t
和扩展整型是在C99推出。对于 C,当char
类型可用时,没有特别的理由定义 8 位扩展整数类型。
UPDATE:
更新:
I'm not entirely comfortable with this conclusion. int8_t
and uint8_t
were introduced in C99. In C, it doesn't particularly matter whether they're character types or not; there are no operations for which the distinction makes a real difference. (Even putc()
, the lowest-level character output routine in standard C, takes the character to be printed as an int
argument). int8_t
, and uint8_t
, if they're defined, will almost certainly be defined as character types -- but character types are just small integer types.
我对这个结论并不完全满意。int8_t
并uint8_t
在 C99 中引入。在 C 中,它们是否是字符类型并不特别重要;没有任何操作的区别会产生真正的区别。(即使putc()
是标准 C 中最低级别的字符输出例程,也将要打印的字符作为int
参数)。int8_t
, 和uint8_t
,如果它们被定义,几乎肯定会被定义为字符类型——但字符类型只是小整数类型。
C++ provides specific overloaded versions of operator<<
for char
, signed char
, and unsigned char
, so that std::cout << 'A'
and std::cout << 65
produce very different output. Later, C++ adopted int8_t
and uint8_t
, but in such a way that, as in C, they're almost certainly character types. For most operations, this doesn't matter any more than it does in C, but for std::cout << ...
it does make a difference, since this:
C++ 提供了operator<<
for 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;
will probably print the letter A
rather than the number 65
.
可能会打印字母A
而不是数字65
。
If you want consistent behavior, add a cast:
如果您想要一致的行为,请添加演员表:
uint8_t x = 65;
std::cout << int(x); // or static_cast<int>(x) if you prefer
I think the root of the problem is that there's something missing from the language: very narrow integer types that are not character types.
我认为问题的根源在于语言中缺少一些东西:不是字符类型的非常窄的整数类型。
As for the intent, I could speculate that the committee members either didn't think about the issue, or decided it wasn't worth addressing. One could argue (and I would) that the benefits of adding the [u]int*_t
types to the standard outweighs the inconvenience of their rather odd behavior with std::cout << ...
.
至于意图,我可以推测委员会成员要么没有考虑这个问题,要么认为它不值得解决。有人可能会争辩说(我也会)将[u]int*_t
类型添加到标准中的好处超过了它们在std::cout << ...
.
回答by Cassio Neri
I'll answer your questions in reverse order.
我会以相反的顺序回答你的问题。
Does the standard specify whether this type can or will be a character type?
标准是否指定此类型是否可以或将是字符类型?
Short answer: int8_t
is signed char
in the most popular platforms (GCC/Intel/Clang on Linux and Visual Studio on Windows) but might be something else in others.
简短的回答:int8_t
是signed char
最流行的平台(GCC /英特尔/锵在Linux和Visual Studio在Windows上),但可能会在其他别的东西。
The long answer follows.
长答案如下。
Section 18.4.1 of the C++11 Standard provides the synopsis of <cstdint>
which includes the following
C++11 标准的第 18.4.1 节提供了概要<cstdint>
,包括以下内容
typedef
signed integer typeint8_t; //optional
typedef
有符号整数类型int8_t; //optional
Later in the same section, paragraph 2, it says
稍后在同一节的第 2 段中,它说
The header [
<cstdint>
] defines all functions, types, and macros the same as 7.18 in the C standard.
标头 [
<cstdint>
] 定义了与C 标准中的7.18 相同的所有函数、类型和宏。
where C standard means C99 as per 1.1/2:
其中 C 标准是指按照 1.1/2 的 C99:
C ++ is a general purpose programming language based on the C programming language as described in ISO/IEC 9899:1999 Programming languages — C(hereinafter referred to as the C standard).
C++ 是一种基于 C 编程语言的通用编程语言,如ISO/IEC 9899:1999 编程语言 — C(以下简称C 标准)中所述。
Hence, the definition of int8_t
is to be found in Section 7.18 of the C99 standard. More precisely, C99's Section 7.18.1.1 says
因此,int8_t
可以在 C99 标准的第 7.18 节中找到的定义。更准确地说,C99 的第 7.18.1.1 节说
The
typedef
nameintN_t
designates a signed integer type with widthN
, no padding bits, and a two's complement representation. Thus, int8_t denotes a signed integer type with a width of exactly 8 bits.
该
typedef
名称intN_t
指定具有宽度N
、无填充位和二进制补码表示的有符号整数类型。因此,int8_t 表示宽度正好为 8 位的有符号整数类型。
In addition, C99's Section 6.2.5/4 says
此外,C99 的第 6.2.5/4 节说
There are five standard signed integer types, designated as signed char, short int, int, long int, and long long int. (These and other types may be designated in several additional ways, as described in 6.7.2.) There may also be implementation-defined extended signed integer types. The standard and extended signed integer types are collectively called signed integer types.
有五种标准的有符号整数类型,指定为signed char、short int、int、long int和long long int。(这些和其他类型可以通过几种额外的方式指定,如 6.7.2 中所述。)也可能存在实现定义的扩展有符号整数类型。该标准和整数类型扩展的有符号统称为整数类型的签署。
Finally, C99's Section 5.2.4.2.1 imposes minimum sizes for standard signed integer types. Excluding signed char
, all others are at least 16 bits long.
最后,C99 的第 5.2.4.2.1 节规定了标准有符号整数类型的最小大小。不包括signed char
,所有其他人的长度至少为 16 位。
Therefore, int8_t
is either signed char
or an 8 bits long extended (non standard) signed integer type.
因此,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
.
glibc(GNU C 库)和 Visual Studio C 库都定义int8_t
为signed char
. Intel 和 Clang,至少在 Linux 上,也使用 libc,因此,这同样适用于它们。因此,在最流行的平台上int8_t
是signed char
.
Given this C++11 program, should I expect to see a number or a letter? Or not make expectations?
鉴于这个 C++11 程序,我应该期望看到一个数字还是一个字母?还是不做期望?
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 DyPfor pointing this out to me.)
简短回答:在最流行的平台(Linux 上的 GCC/Intel/Clang 和 Windows 上的 Visual Studio)中,您肯定会看到字母“A”。在其他平台上,您可能会看到65
。(感谢DyP向我指出这一点。)
In the sequel, all references are to the C++11 standard (current draft, N3485).
在续集中,所有引用均参考 C++11 标准(当前草案,N3485)。
Section 27.4.1 provides the synopsis of <iostream>
, in particular, it states the declaration of cout
:
第 27.4.1 节提供了 的概要<iostream>
,特别是,它声明了cout
:
extern ostream cout;
Now, ostream
is a typedef
for a template specialization of basic_ostream
as per Section 27.7.1:
现在,ostream
是根据第 27.7.1 节typedef
的模板basic_ostream
特化:
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:
第 27.7.3.6.4 节提供了以下声明:
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).
如果int8_t
是,signed char
则将调用此重载。同一部分还指定此调用的效果是打印字符(而不是数字)。
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 promotedto int
. On the other hand, 4.7/1 and 4.7/2 gives that int8_t
can be convertedto 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)
现在,让我们考虑int8_t
扩展有符号整数类型的情况。显然,标准没有指定operator<<()
非标准类型的重载,但由于提升和转换,提供的重载之一可能会接受调用。实际上,int
至少有 16 位长,可以表示 的所有值int8_t
。然后 4.5/1 给出int8_t
可以提升到int
. 另一方面, 4.7/1 和 4.7/2 给出int8_t
可以转换为signed char
. 最后,13.3.3.1.1 产生了在重载解析过程中促进优于转换。因此,以下重载(在 23.7.3.1 中声明)
basic_ostream& basic_ostream::operator<<(int n);
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
.
将打印65
。
Update:
更新:
1. Corrected the post following DyP's comment.
1. 更正了DyP评论后的帖子。
2. Added the following comments on the possibility of int8_t
be a typedef
for char
.
2. 添加了以下关于int8_t
成为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:
如上所述,C99 标准(上面引用的第 6.2.5/4 节)定义了 5 种标准有符号整数类型(char
不是其中之一),并允许实现添加它们的 onw,它们被称为非标准有符号整数类型。C++ 标准加强了第 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.
有五种标准的有符号整数类型:“signed char”、“short int”、“int”、“long int”和“long long int”[...] 也可能有实现定义的扩展有符号整数类型。标准的和扩展的有符号整数类型统称为有符号整数类型。
Later, in the same section, paragraph 7 says:
后来,在同一节中,第 7 段说:
Types
bool
,char
,char16_t
,char32_t
,wchar_t
, and the signed and unsigned integer typesare collectively called integral types. A synonym for integral type is integer type.
类型
bool
,char
,char16_t
,char32_t
,wchar_t
,和符号和无符号整数类型统称为整数类型。整数类型的同义词是整数类型。
Therefore, char
is an integer type but char
is neither a signed integer type nor an unsigned integer typeand Section 18.4.1 (quoted above) says that int8_t
, when present, is a typedef
for a signed integer type.
因此,char
是整数类型,但char
既不是有符号整数类型也不是无符号整数类型,第 18.4.1 节(上面引用)说int8_t
,当存在时,是typedef
有符号整数类型的 a。
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:
可能令人困惑的是,根据实现,char
可以采用与 a 相同的值signed char
。特别是,char
可能有一个标志,但它仍然不是signed char
. 这在第 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.
[...] Plain
char
、signed char
和unsigned char
是三种不同的类型。[...] 在任何特定的实现中,普通char
对象可以采用与 asigned char
或 an相同的值unsigned char
;哪个是实现定义的。
This also implies that char
is nota signed integer type as defined by 3.9.1/2.
这也意味着,char
是不通过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.
3. 我承认我的解释,特别是“char
既不是有符号整数类型也不是无符号整数类型”这句话有点争议。
To strength my case, I would like to add that Stephan T. Lavavej said the very same thing hereand Johannes Schaub - litbalso used the same sentence in a comment on thispost.
为了加强我的观点,我想补充一点,Stephan T. Lavavej 在这里说了同样的话,Johannes Schaub - litb在这篇文章的评论中也使用了相同的句子。
回答by Rapptz
The working draft copy I have, N3376, specifies in [cstdint.syn] § 18.4.1 that the int types are typically typedefs.
我拥有的工作草案副本 N3376 在 [cstdint.syn] § 18.4.1 中指定 int 类型通常是 typedef。
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.
因为唯一的要求是它必须是 8 位,所以 typedef 到 char 是可以接受的。
回答by richselian
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", ...)
.
char
/ signed char
/unsigned char
三种不同类型的,并且char
不总是8位。在大多数平台上,它们都是 8 位整数,但 std::ostream 只定义>>
了像scanf("%c", ...)
.