15

これはばかげた質問かもしれませんが、誰かが C++11 と C11 の標準リファレンスを提供してくれませんか:

charデフォルトで昇格されていintますか?

ここで少し背景を説明します。C と C++ の両方に、既定の引数昇格の概念があります(C++11: 5.2.2/7; C11: 6.5.2.2/6)。これにより、次の呼び出しで引数が昇格されます。

void f(int, ...);

float a = 1; short int b = 2; char c = 'x';

f(0, a, b, c);

関数呼び出しの場合、aは に変換されdoublebは に変換されintます。しかし、どうなりcますか?私は常にcharも に昇格するという印象を受けてきましintたが、基準に関連するステートメントを見つけることができません。

4

2 に答える 2

13

まず、デフォルト引数の昇格

6.5.2.2

呼び出された関数を示す式の型がプロトタイプを含まない場合、各引数に対して整数昇格が実行され、型が float の引数は double に昇格されます。これらはデフォルト引数のプロモーションと呼ばれます。

整数の昇格の場合:

6.3.1.1

以下は、int または unsigned int を使用できる式で使用できます。

  • 整数変換ランクが int および unsigned int のランク以下である整数型 (int または unsigned int 以外) のオブジェクトまたは式。

int が元の型のすべての値を表すことができる場合 (ビットフィールドの幅によって制限されるため)、値は int に変換されます。それ以外の場合は、unsigned int に変換されます。これらは 整数プロモーションと呼ばれます。

したがって、C の場合、少なくとも aはデフォルトでorcharに昇格されます。intunsigned int

于 2012-08-16T11:07:36.007 に答える
8

C++

C++ 2011 (ISO/IEC 14882:2011) では、関連する部分は次のようになります。

§5.2.2 関数呼び出し [expr.call]

¶6 関数は、引数の数よりも少ない引数 (デフォルト引数 (8.3.6) を宣言することによって) またはより多くの引数 (省略記号、...、または関数パラメーター パック (8.3.5) を使用することによって) を受け入れるように宣言できます。関数定義のパラメーター (8.4)。[注: これは、省略記号 (...) または関数パラメーター パックが使用されている場合を除き、各引数に対してパラメーターを使用できることを意味します。—終わりのメモ]

¶7 与えられた引数にパラメータがない場合、引数は、受信関数が va_arg (18.10) を呼び出して引数の値を取得できるように渡されます。[注: この段落は、関数パラメーター パックに渡される引数には適用されません。関数パラメーター パックは、テンプレートのインスタンス化 (14.5.3) 中に展開されるため、関数テンプレートの特殊化が実際に呼び出されると、そのような各引数には対応するパラメーターがあります。--end note] 左辺値から右辺値 (4.1)、配列からポインター (4.2)、および関数からポインター (4.3) への標準変換は、引数式に対して実行されます。(cv 修飾されている可能性がある) 型 std::nullptr_t を持つ引数は、型 void* (4.10) に変換されます。これらの変換の後、引数が算術、列挙、ポインター、メンバーへのポインター、またはクラス型を持たない場合、プログラムの形式が正しくありません。自明でないコピー コンストラクタ、自明でないムーブ コンストラクタ、または自明でないデストラクタを持ち、対応するパラメータを持たないクラス型 (第 9 節) の潜在的に評価される引数を渡すことは、実装定義のセマンティクスで条件付きでサポートされます。

引数が、整数昇格 (4.5) の対象となる整数型または列挙型、または浮動小数点昇格 (4.6) の対象となる浮動小数点型の場合、引数の値は、呼び出しの前に昇格された型に変換されます。 . これらのプロモーションは、デフォルト引数プロモーションと呼ばれます。

強調するために、最後の 2 つの文を分けました。それらは、標準のパラグラフ 7 の連続部分です。

§4.5 インテグラル プロモーション [conv.prom]

¶1 boolchar16_tchar32_t、またはwchar_t整数変換ランク (4.13) が のランクよりも小さい整数型の prvalueは、ソース型のすべての値を表すことができる場合int、型の prvalue に変換できます。それ以外の場合は、ソースの prvalue を type の prvalue に変換できます。intintunsigned int

¶2 型char16_tchar32_t、またはwchar_t(3.9.1) の prvalue は、その基になる型のすべての値を表すことができる次の型の最初の型の prvalue に変換できます: intunsigned intlong intunsigned long intlong long int、またはunsigned long long int。そのリスト内のいずれの型も、その基になる型のすべての値を表すことができない場合、型char16_tchar32_t、またはwchar_tの prvalue は、その基になる型の prvalue に変換できます。

等。


C には、引数がデフォルトで昇格される 2 つのコンテキストがあります。1つは、関数のスコープ内にプロトタイプがない場合(最初は別の回答でカバーされています)、2つ目は省略記号のあるプロトタイプがある場合です。もちろん、C++ では最初のケースはまったく許可されません。これらの引用は、別の回答で選択されたものと同じ標準のセクションからのものですが、ここのスニペットはやや長くなっています。それらは標準の独立した分析によって発見されました。セクションが同じであることに気付いたのは、クロスチェックを行ったときだけでした。

C 2011 (ISO/IEC 9899:2011) では、関連する部分は次のようです。

§6.5.2.2 関数呼び出し

¶6 呼び出された関数を示す式がプロトタイプを含まない型を持つ場合、各引数に対して整数昇格が実行され、float 型の引数は double に昇格されます。これらは、デフォルト引数プロモーションと呼ばれます。引数の数がパラメーターの数と等しくない場合、動作は未定義です。関数がプロトタイプを含む型で定義されており、プロトタイプが省略記号 (, ...) または昇格後の引数の型がパラメーターの型と互換性がない場合、動作は未定義です。関数がプロトタイプを含まない型で定義されており、昇格後の引数の型が昇格後のパラメーターの型と互換性がない場合、次の場合を除き、動作は未定義です。

— 一方の昇格型は符号付き整数型で、もう一方の昇格型は対応する符号なし整数型であり、値は両方の型で表現可能です。

— どちらのタイプも、文字タイプまたは void の修飾または非修飾バージョンへのポインターです。

¶7 呼び出された関数を示す式がプロトタイプを含まない型を持っている場合、引数は、あたかも代入によるかのように、対応するパラメーターの型に暗黙的に変換され、各パラメーターの型が非修飾バージョンになります。その宣言された型。関数プロトタイプ宣言子の省略記号表記により、最後に宣言されたパラメーターの後で引数の型変換が停止します。デフォルトの引数昇格は、末尾の引数に対して実行されます。

「整数プロモーション」は §6.3.1.1 で定義されています。

§6.3.1 算術オペランド

§6.3.1.1 ブール値、文字、および整数

¶1 すべての整数型には、次のように定義された整数変換ランクがあります。

— 表現が同じであっても、2 つの符号付き整数型が同じランクになることはありません。

— 符号付き整数型のランクは、精度の低い符号付き整数型のランクより大きくなければなりません。

— long long int のランクは、long int のランクよりも大きくなければならず、long int のランクよりも大きくなければなりません。これは、int のランクよりも大きくなければなりません。これは、short int のランクよりも大きくなければならず、signed char のランクよりも大きくなければなりません。

— 符号なし整数型のランクは、対応する符号付き整数型がある場合、そのランクと等しくなければなりません。

— 標準整数型のランクは、同じ幅の拡張整数型のランクより大きくなければなりません。

— char のランクは、signed char および unsigned char のランクと等しくなければなりません。

— _Bool のランクは、他のすべての標準整数型のランクよりも小さくなければなりません。

— 列挙型のランクは、互換性のある整数型のランクと等しくなければならない (6.7.2.2 を参照)。

— 同じ精度を持つ別の拡張符号付き整数型に対する拡張符号付き整数型のランクは、実装定義ですが、整数変換ランクを決定するための他の規則に従います。

— すべての整数型 T1、T2、および T3 について、T1 のランクが T2 よりも大きく、T2 のランクが T3 よりも大きい場合、T1 のランクは T3 よりも大きくなります。

¶2 以下は、intorunsigned intを使用できる式のどこでも使用できます。

— 整数変換ランクがand のランク以下である整数型 (intまたは以外) のオブジェクトまたは式。unsigned intintunsigned int

_Bool— タイプ、intsigned int、またはのビットフィールドunsigned int

が元の型のすべての値を表すことができる場合int(ビットフィールドの場合、幅によって制限されるため)、値はint;に変換されます。それ以外の場合は、に変換されますunsigned int。これらは整数プロモーションと呼ばれます。58)他のすべての型は、整数の昇格によって変更されません。

58)整数昇格は、通常の算術変換の一部として、特定の引数式、単項 +、-、および ~ 演算子のオペランド、およびシフト演算子の両方のオペランドにのみ適用されます。副次句。


ある時点で、質問に function がリストされていたことに注意してくださいvoid f(...);。これは C++ 関数であり、C 関数ではありません。C では、省略記号を関数の唯一の引数として使用することはできません。その後、質問は更新されvoid f(int, ...);、C と C++ の両方で有効です。

于 2012-09-09T12:16:34.900 に答える