Int8 t и uint8 t предназначены для типов char?


учитывая эту программу C++11, должен ли я ожидать увидеть число или букву? Или не надеждами?

#include <cstdint>
#include <iostream>

int main()
{
    int8_t i = 65;
    std::cout << i;
}

указывает ли стандарт, может ли этот тип быть или будет символьным типом?

5 54

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 - это определение типа из 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 (т. е. 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. Оба 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 обозначает целочисленный тип со знаком width N, отсутствие битов прокладки, и дополнения 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 также использовал то же самое предложение в комментарии к этой должность.

char/signed char/unsigned char три разных типа, и char не всегда 8 бит. на большинстве платформ все они являются 8-битными целыми числами, но std:: ostream определяет только версию char >> для поведения типа scanf("%c", ...).