Int8 t и uint8 t предназначены для типов char?
учитывая эту программу C++11, должен ли я ожидать увидеть число или букву? Или не надеждами?
#include <cstdint>
#include <iostream>
int main()
{
int8_t i = 65;
std::cout << i;
}
указывает ли стандарт, может ли этот тип быть или будет символьным типом?
5 ответов:
из § 18.4.1 [cstdint.syn] из C++0x FDIS (N3290),
int8_t
является необязательным typedef, который указывается следующим образом:namespace std { typedef signed integer type int8_t; // optional //... } // namespace std
§ 3.9.1 [basic.фундаментальные] состояния:
пять стандартные целочисленные типы со знаком: "
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
может быть typedefchar
предоставилchar
объекты принимают подписанные значения; однако это не так, какchar
не входит в список целочисленные типы со знаком (стандарт и, возможно, расширенная подпись целочисленный тип.) Смотрите также комментарии Стефана т. Лававея onstd::make_unsigned
иstd::make_signed
.поэтому, либо
int8_t
- это определение типа изsigned char
или это расширенная знаковый целочисленный тип, объекты которого занимают ровно 8 бит памяти.чтобы ответить на ваш вопрос, однако, вы не должны делать предположений. Потому что функции обеих форм
x.operator<<(y)
иoperator<<(x,y)
были определены, § 13.5.3 [over.binary] говорит, что мы ссылаемся на § 13.3.1.2 [over.спичка.опер] к определите интерпретациюstd::cout << i
. § 13.3.1.2 в свою очередь говорит, что реализация выбирает из набора функций-кандидатов в соответствии с § 13.3.2 и § 13.3.3. Затем мы обратимся к § 13.3.3.2 [over.микросхема.ранг] чтобы определить, что:
- The
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)
функция-член будет называемый.в случае
std::cout << u
наu
a
int8_t
ровно 8 бит в ширину (если он существует).только предопределенные целочисленные типы, которые могут быть 8 бит
char
,unsigned char
иsigned char
. Обаshort
иunsigned short
должна быть не менее 16 бит.так
int8_t
должен быть typedef для любогоsigned char
или обычныйchar
(последний, если равнина есть).если вы хотите напечатать
int8_t
значение как целое число, а не как персонаж, можно явно преобразовать его вint
.в принципе, компилятор C++ может определить 8-битный расширенный целочисленный тип (возможно, называется что-то вроде
__int8
) иint8_t
typedef для него. Единственная причина, по которой я могу это сделать, - это не делатьint8_t
тип характера. Я не знаю ни одного компилятора C++, который действительно сделал это.и
int8_t
и расширенные целочисленные типы были введены в C99. Для C, нет никакой особой причины, чтобы определить 8-бит расширенный целочисленный тип, когдаchar
типы доступны.обновление:
я не совсем согласен с этим выводом.
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
типы к стандарту перевешивают неудобство их довольно странного поведения сstd::cout << ...
.
рабочий черновик, который у меня есть, N3376, указывает в [cstdint.Син] § 18.4.1 что типа int, как правило, являются определения типов.
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
поскольку единственное требование состоит в том, что он должен быть 8 бит, то typedef для char является приемлемым.
я отвечу на ваши вопросы в обратном порядке.
указывает ли стандарт, может ли этот тип быть или будет символьным типом?
короткий ответ::
int8_t
иsigned char
в самых популярных платформах (GCC/Intel/Clang на Linux и Visual Studio на Windows), но может быть что-то еще в других.длинный ответ ниже.
в разделе 18.4.1 стандарта C++11 приводится краткое описание
<cstdint>
который включает в себя следующее
typedef
целочисленный тип со знакомint8_t; //optional
позже в том же разделе, пункт 2, там написано
заголовок [
<cstdint>
] определяет все функции, типы и макросы так же, как 7.18 в стандарт C.где стандарт C означает C99 согласно 1.1 / 2:
C ++ - это язык программирования общего назначения на основе языка программирования C, как описано в ISO / IEC 9899: 1999 языки программирования-C (далее стандарт C).
отсюда и определение
int8_t
находится в разделе 7.18 стандарта C99. Точнее, раздел 7.18.1.1 C99 говоритThe
typedef
имяintN_t
обозначает целочисленный тип со знаком widthN
, отсутствие битов прокладки, и дополнения 2 представление. Таким образом,int8_t обозначает целочисленный тип со знаком шириной ровно 8 бит.кроме того, в разделе 6.2.5/4 C99 говорится
пять стандартные целочисленные типы со знаком, обозначенного как подпись Чара, short int,int, long int и длинный инт. (Эти и другие типы могут быть обозначены в нескольких дополнительных способами, как описано в 6.7.2.) Там также может быть реализация-определенные расширенные целочисленные типы со знаком. Элемент стандартные и расширенные целочисленные типы со знаком совместно называются целочисленными типами со знаком.
наконец, раздел 5.2.4.2.1 C99 устанавливает минимальные размеры для стандартных целочисленных типов со знаком. Исключая
signed char
, все остальные-не менее 16 бит.таким образом,
int8_t
либоsigned char
или 8 бит продлен (не стандартный) целочисленный тип со знаком.обе версии glibc (стандартная библиотека языка Си) и Visual студии с библиотекой определить
int8_t
какsigned char
. Intel и Clang, по крайней мере на Linux, также используют libc и, следовательно, то же самое относится к ним. Поэтому на самых популярных платформахint8_t
иsigned char
.учитывая эту программу C++11, должен ли я ожидать увидеть число или букву? Или не надеждами?
короткий ответ:: в самых популярных платформы (GCC / Intel / Clang на Linux и Visual Studio на Windows) вы обязательно увидите букву "А". На других платформах вы можете увидеть
65
хотя. (Спасибо DyP за то, что указал мне на это.)в дальнейшем все ссылки относятся к стандарту C++11 (текущий проект, N3485).
в разделе 27.4.1 приводится краткое описание
<iostream>
, в частности, в нем говорится о декларацииcout
:extern ostream cout;
теперь
ostream
- этоtypedef
для шаблона специализацииbasic_ostream
согласно разделу 27.7.1:template <class charT, class traits = char_traits<charT> > class basic_ostream; typedef basic_ostream<char> ostream;
в разделе 27.7.3.6.4 содержится следующее заявление:
template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, signed char c);
если
int8_t
иsigned char
тогда это перегрузка, которая будет называться. В том же разделе также указывается, что результатом этого вызова является печать символа (а не числа).Теперь рассмотрим случай, когда
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
будет называться. Это означает, что этот код
int8_t i = 65; std::cout << i;
печати
65
.обновление:
1. Исправлено сообщение следующее DyPкомментарий.
2. Добавить следующее комментарии о возможности
int8_t
бытьtypedef
наchar
.как уже было сказано, стандарт C99 (раздел 6.2.5/4 цитируется выше) определяет 5 стандартных целочисленных типов со знаком (
char
не является одним из них) и позволяет реализациям добавлять свои onw, которые называются нестандартными целочисленными типами со знаком. Стандарт C++ усиливает это определение в разделе 3.9.1/2:существует пять стандартных целочисленных типов подпись : "подпись Чара", "короткий интервал", "интервал", "долгий интервал", и "длинный инт" [...] Также могут быть определенные реализацией расширенные целочисленные типы со знаком. Стандартные и расширенные целочисленные типы со знаком совместно называются целочисленные типы со знаком.
позже, в том же разделе, пункт 7 говорит:
типы
bool
,char
,char16_t
,char32_t
,wchar_t
,и целочисленные типы со знаком и без знака называются Интеграл типы. Синонимом интегрального типа является целое число типа.таким образом,
char
является целочисленным типом, ноchar
не является ни целочисленным типом со знаком, ни целочисленным типом без знака и раздел 18.4.1 (цитируется выше) говорит, чтоint8_t
, если он присутствует, являетсяtypedef
для целочисленного типа со знаком.что может быть запутанным, что, в зависимости от реализации,
char
может принимать те же значения, что иsigned char
. В особенно,char
может быть знак, но это все-таки неsigned char
. Это явно сказано в разделе 3.9.1 / 1:[...] Равнина
char
,signed char
иunsigned char
are три различных типа. [...] В любой конкретной реализации, простойchar
объект может принимать либо те же значения, что иsigned char
илиunsigned char
, которое определяется реализацией.это также означает, что
char
и не a целочисленный тип со знаком, определенный в 3.9.1 / 2.3. Я признаю, что моя интерпретация и, в частности, предложение"
char
не является ни целочисленным типом со знаком, ни целочисленным типом без знака" является немного спорным.чтобы укрепить мое дело, я хотел бы добавить, что Стефан т. Лававей сказал то же самое здесь и Johannes Schaub-litb также использовал то же самое предложение в комментарии к этой должность.