この C++11 プログラムを考えると、数字または文字が表示されることを期待できますか? それとも期待しない?
#include <cstdint>
#include <iostream>
int main()
{
int8_t i = 65;
std::cout << i;
}
標準は、このタイプが文字タイプである可能性があるか、または文字タイプになるかを指定していますか?
この C++11 プログラムを考えると、数字または文字が表示されることを期待できますか? それとも期待しない?
#include <cstdint>
#include <iostream>
int main()
{
int8_t i = 65;
std::cout << i;
}
標準は、このタイプが文字タイプである可能性があるか、または文字タイプになるかを指定していますか?
ご質問には逆順でお答えします。
標準は、このタイプが文字タイプである可能性があるか、または文字タイプになるかを指定していますか?
簡単な答え:最も一般的なプラットフォーム (Linux の GCC/Intel/Clang および Windows の Visual Studio) にありますが、他のプラットフォームでは別のものである可能性がありますint8_t
。signed char
長い答えが続きます。
<cstdint>
C++11 標準のセクション 18.4.1 には、以下を含む概要が記載されています。
typedef
符号付き整数型int8_t; //optional
同じセクションの後半、パラグラフ 2 には、次のように書かれています。
ヘッダー [ ] は、 C 標準
<cstdint>
の 7.18 と同じように、すべての関数、型、およびマクロを定義します。
ここで、C 標準は 1.1/2 による C99 を意味します。
C ++ は、 ISO/IEC 9899:1999 プログラミング言語 - C (以降、C 標準と呼びます)に記載されている C プログラミング言語に基づく汎用プログラミング言語です。
したがって、 の定義はint8_t
C99 標準のセクション 7.18 にあります。より正確には、C99 のセクション 7.18.1.1 は言う
この
typedef
名前は、 width 、パディング ビットなし、および 2 の補数表現をintN_t
持つ符号付き整数型を指定します。N
したがって、int8_t は、幅が正確に 8 ビットの符号付き整数型を示します。
さらに、C99 のセクション 6.2.5/4 は言う
signed char、short int、int、long int、およびlong long intとして指定される5 つの標準の符号付き整数型があります。(これらの型およびその他の型は、6.7.2 で説明されているように、いくつかの追加の方法で指定できます。)実装定義の拡張符号付き整数型も存在する場合があります。標準および拡張の符号付き整数型をまとめて符号付き整数型と呼びます。
最後に、C99 のセクション 5.2.4.2.1 では、標準の符号付き整数型の最小サイズが規定されています。を除いsigned char
て、他のすべては少なくとも 16 ビット長です。
したがって、int8_t
はsigned char
または 8 ビット長の拡張 (非標準) 符号付き整数型です。
glibc (GNU C ライブラリ) と Visual Studio C ライブラリの両方が として定義int8_t
されていsigned char
ます。少なくとも Linux では、Intel と Clang も libc を使用しているため、同じことが当てはまります。したがって、最も人気のあるプラットフォームint8_t
ではsigned char
.
この C++11 プログラムを考えると、数字または文字が表示されることを期待できますか? それとも期待しない?
簡単な答え: 最も一般的なプラットフォーム (Linux の GCC/Intel/Clang および Windows の Visual Studio) では、文字 'A' が必ず表示されます。ただし、他のプラットフォームでは表示される場合が65
あります。(これを指摘してくれたDyPに感謝します。)
続編では、すべての参照は C++11 標準 (現在のドラフト、N3485) に対するものです。
セクション 27.4.1 は の概要を提供し<iostream>
、特に、次の宣言を述べていますcout
。
extern ostream cout;
現在、セクション 27.7.1 に従ってテンプレートを特殊化ostream
しています。typedef
basic_ostream
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<<()
非標準型のオーバーロードを指定していませんが、プロモーションと変換のおかげで、提供されたオーバーロードの 1 つが呼び出しを受け入れる可能性があります。実際、int
は少なくとも 16 ビット長で、 のすべての値を表すことができますint8_t
。次に、 に昇格int8_t
できる4.5/1 が得られます。一方、 4.7/1 と 4.7/2 はに変換できます。最後に、13.3.3.1.1 では、オーバーロードの解決中に変換よりも昇格が優先されます。したがって、次のオーバーロード (23.7.3.1 で宣言)int
int8_t
signed char
basic_ostream& basic_ostream::operator<<(int n);
が呼び出されます。つまり、このコードは
int8_t i = 65;
std::cout << i;
印刷されます65
。
アップデート:
1 . DyPのコメントに続いて、投稿を修正しました。
2 . forでint8_t
ある可能性について、次のコメントを追加しました。typedef
char
前述のように、C99 標準 (上記のセクション 6.2.5/4) は 5 つの標準の符号付き整数型 (char
これらの 1 つではありません) を定義し、実装が非標準の符号付き整数型と呼ばれる onw を追加できるようにします。C++ 標準は、セクション 3.9.1/2 でその定義を強化します。
標準の符号付き整数型には、「signed char」、「short int」、「int」、「long int」、および「long long int」の 5 つがあります [...] 実装定義の拡張符号付き整数型もある場合があります。標準および拡張の符号付き整数型をまとめて符号付き整数型と呼びます。
その後、同じセクションの第 7 段落で次のように述べています。
、、、、、および符号付き整数型
bool
と符号なし整数型char
をまとめて整数型と呼びます。整数型の同義語は整数型です。char16_t
char32_t
wchar_t
したがって、char
は整数型ですがchar
、符号付き整数型でも符号なし整数型でもありません。セクション 18.4.1 (上記で引用) ではint8_t
、 が存在する場合、 は符号付き整数型の であると述べていtypedef
ます。
ややこしいのは、実装によっては、char
が a と同じ値を取る可能性があることsigned char
です。特に、char
記号はあるかもしれませんが、まだsigned char
. これは、セクション 3.9.1/1 で明示的に述べられています。
[...] Plain
char
、signed char
、およびunsigned char
は3 つの異なるタイプです。[...] 特定の実装では、プレーンオブジェクトは aまたは;char
と同じ値を取ることができます。どちらが実装定義です。signed char
unsigned char
これは、 が 3.9.1/2 で定義されている符号付き整数型でchar
はないことも意味します。
3 . 私の解釈、具体的には、「char
符号付き整数型でも符号なし整数型でもない」という文は、少し物議をかもしていることを認めます。
私の主張を強化するために、Stephan T. Lavavej がここでまったく同じことを言い、Johannes Schaub - litbもこの投稿へのコメントで同じ文を使用したことを付け加えたいと思います。
私が持っているワーキング ドラフト コピー 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
唯一の要件は 8 ビットでなければならないということなので、char への typedef は受け入れられます。
char
//は 3 つの異なる型であり、asigned char
は必ずしも 8 ビットではありません。ほとんどのプラットフォームでは、それらはすべて 8 ビットの整数ですが、 std::ostream はのような動作に対してchar バージョンのみを定義しました。unsigned char
char
>>
scanf("%c", ...)