Int8 t и uint8 t предназначены для типов символов?
учитывая эту программу 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
может быть typedef char
предоставил char
объекты принимают подписанные значения; однако это не так, как char
не входит в список целочисленные типы со знаком (стандарт и, возможно, расширенная подпись целочисленный тип.) См. также комментарии Стефана т. Лававея on std::make_unsigned
и std::make_signed
.
поэтому, либо int8_t
является typedef signed char
или это расширенная знаковый целочисленный тип, объекты которого занимают ровно 8 бит памяти.
чтобы ответить на ваш вопрос, вы не должны делать предположений. Потому что функции обеих форм x.operator<<(y)
и operator<<(x,y)
были определены, § 13.5.3 [за.binary] говорит, что мы ссылаемся на § 13.3.1.2 [over.спичка.oper] to определите интерпретацию std::cout << i
. § 13.3.1.2 в свою очередь говорит, что реализация выбирает из набора функций-кандидатов в соответствии с § 13.3.2 и § 13.3.3. Затем мы рассмотрим § 13.3.3.2 [over.микросхема.ранг], чтобы определить, что:
- на
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
. Оба!--6--> и 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.syn] § 18.4.1, что типы int обычно являются 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
поскольку единственным требованием является то, что он должен быть 8 бит, то typedef для char является приемлемым.
я отвечу на ваши вопросы в обратном порядке.
указывает ли стандарт, может ли этот тип быть или будет символьным типом?
короткий ответ:: int8_t
is 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. Точнее, раздел C99 7.18.1.1 говорит
на
typedef
имяintN_t
обозначает целочисленный тип со знаком widthN
, отсутствие битов прокладки, и комплект 2 представление. Таким образом, int8_t обозначает знаковый целочисленный тип с шириной ровно 8 бит.
кроме того, в разделе 6.2.5 / 4 C99 говорится
пять стандартные целочисленные типы со знаком, обозначенного как подписано char, короткий int, int, длинный int и длинный длинный int. (Эти и другие типы могут быть обозначены в нескольких дополнительных способами, как описано в 6.7.2.) Также могут быть реализация-определенные расширенные целочисленные типы со знаком. The стандартные и расширенные целочисленные типы со знаком в совокупности называются целочисленными типами со знаком.
наконец, раздел 5.2.4.2.1 C99 устанавливает минимальные размеры для стандартных целочисленных типов со знаком. Кроме signed char
, все остальные по крайней мере 16 бит длиной.
таким образом, int8_t
либо signed char
или 8 бит продлен (не standard) целочисленный тип со знаком.
как glibc (библиотека GNU C), так и библиотека Visual Studio C определяют int8_t
as signed char
. Intel и Clang, по крайней мере, на Linux, также используют libc и, следовательно, то же самое относится к ним. Поэтому в самых популярных платформах int8_t
is signed char
.
учитывая эту программу c++11, должен ли я ожидать увидеть число или букву? Или не надеждами?
короткий ответ:: в самых популярных платформы (GCC / Intel / Clang в Linux и Visual Studio в Windows) вы обязательно увидите букву "A". На других платформах вы можете получить see 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
is signed char
тогда это перегрузка, которая будет называться. В том же разделе также указывается, что результатом этого вызова является печать символа (а не номера).
Теперь рассмотрим случай, когда int8_t
- расширенный целочисленный тип со знаком. Очевидно, что стандарт не укажите перегрузки operator<<()
для нестандартных типов, но благодаря акциям и конвертациям одна из предоставленных перегрузок может принять вызов. Действительно,int
имеет длину не менее 16 бит и может представлять все значения int8_t
. Тогда 4.5/1 дает, что int8_t
может быть произведен to int
. С другой стороны, 4.7/1 и 4,7/2 дает, что int8_t
может быть преобразовать to signed char
. Наконец, 13.3.3.1.1 дает, что продвижение предпочтительнее конверсии во время разрешение перегрузки. Следовательно, следующая перегрузка (объявленная в 23.7.3.1)
basic_ostream& basic_ostream:: оператор
будет называться. Это означает, что этот код
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:
существует пять стандартных целочисленных типов со знаком: "signed char", "short int", " int", "long int" и "long long int" [...] Также могут быть определенные реализацией расширенные целочисленные типы со знаком. Стандартные и расширенные целочисленные типы со знаком совместно называются целочисленные типы со знаком.
позже, в том же разделе, пункт 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
- это не знаковый целочисленный тип, ни беззнаковый тип" является несколько спорным.
чтобы подкрепить мое мнение, я хотел бы добавить, что Стефан т. Лававей сказал то же самое здесь и Йоханнес шоб - litb также использовал то же самое предложение в комментарии этой должность.
char
/signed char
/unsigned char
три разных типа, и char
не всегда 8 бит. на большинстве платформ они все 8-битные целочисленные, но std:: ostream определяет только char-версию >>
для поведения типа scanf("%c", ...)
.