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 (т. е. typedef signed 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 обозначает целочисленный тип со знаком width N, отсутствие битов прокладки, и комплект 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", ...).