4

私は同僚に次のような声明を出しました。

「文字は C 式で自動的に整数に昇格されます。CPU は自然なワード サイズで最も速く動作するため、パフォーマンスには問題ありません。

char の昇格動作は、char のランクにより、標準のどこかに記載されていると思います。

これは私が戻ってきた応答です:

「文字はデフォルトで整数に昇格されません。レジスタのサイズは 32 ビットですが、コンパイラの実装として、行内の複数のバイト値を 1 つのレジスタにパックできます。これは常に予測できるとは限りません。自動昇格を確認できるのは、これは、C 標準がコール スタック メモリに 32 ビット値を公式に必要とするため、構造体にラップされていないときに型がコール スタックに渡されるときです. 多くの CPU アーキテクチャでは、32 ビット以外の値のアセンブリ呼び出しが最適化されているため、この場合、CPU またはコンパイラについて仮定を行うことができます。」

誰が正しいのか、何を信じればいいのかわかりません。事実は何ですか?

4

4 に答える 4

8

chars are automatically promoted to integers in C expressions

Yes, they are. C99 section 6.3.1.8, Usual arithmetic conversions:

Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type for the operands and result. For the specified operands, each operand is converted, without change of type domain, to a type whose corresponding real type is the common real type. Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result, whose type domain is the type domain of the operands if they are the same, and complex otherwise. This pattern is called the usual arithmetic conversions:

  • First, if the corresponding real type of either operand is long double, the other operand is converted, without change of type domain, to a type whose corresponding real type is long double.
  • Otherwise, if the corresponding real type of either operand is double, the other operand is converted, without change of type domain, to a type whose corresponding real type is double.
  • Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float.62)
  • Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:
    • If both operands have the same type, then no further conversion is needed.
    • Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
    • Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.
    • Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.
    • Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

Integer promotions are described on Section 6.3.1.1.2:

The following may be used in an expression wherever an int or unsigned int may be used:

  • An object or expression with an integer type whose integer conversion rank is less than or equal to the rank of int and unsigned int.
  • A bit-field of type _Bool, int, signed int, or unsigned int

If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanges by the integer promotions.

The rank of a char is less than or equal to that of an int, so char is included in here.

(As a footnote, it is mentioned that integer promotions are only applied as part of the usual arithmetic conversions, to certain argument expressions, to the operands of the unary +, - and ~, and to both operands of the shift operators).

As mentioned in the comments, integer promotion is also performed on function-call arguments.

于 2015-09-03T19:21:42.127 に答える
4

はい、char足し算などの複数の を含む式。(ただし、カンマ演算子のようなものではありません)、およびその他のいくつかの処理は、昇格された値 (に昇格int) に対して行われます。例を参照してください。N3797、§4.5

あなたの同僚の発言については、多くの間違いがあります。

  • 「レジストリ」(レジスタ)のサイズは一般に 32 ビットではなく、まったくありません。

  • 1 バイトが 8 ビットの場合、もちろん 32 ビットのレジスタは複数のバイトを保持できます
    が、これは関係なく、可能である理由はコンパイラではありません。

  • これが「予測」とはどういうことでしょうか。

  • 標準と 32 ビットに関するビットは完全に間違っています。

  • 整数昇格は関係ありませんstruct

  • 標準では、「スタック」はありません。スタックの概念
    が実際に使用されていることは必須ではありません (他の人が言ったように)。

  • 彼は、すべてが 32 ビットである必要があると言っていますが、CPU
    は他のサイズも処理できるので、確かなことは何も言えませんか? 今何?

...

于 2015-09-03T19:12:38.650 に答える
2

C は、スタックを必要とせず、32 ビット レジスタについて何も指定しません。

整数昇格の理論的根拠の 1 つは、CERTが述べているとおりです。

整数昇格は、中間値のオーバーフローに起因する算術エラーを回避するために実行されます。例えば:

signed char cresult, c1, c2, c3;
c1 = 100;
c2 = 3;
c3 = 4;
cresult = c1 * c2 / c3;

すべての演算子が引数を通常の算術変換の対象にするわけではないことに注意してください。たとえば、代入演算子またはキャスト演算子では整数昇格はありません。

于 2015-09-03T19:10:41.030 に答える
0

論理的には、はい、すべての操作は昇格された値に対して実行されます。ただし、as-ifルールの下では、結果が同一であることを証明できるコンパイラは、実際の昇格を省略することを選択する場合があります。if (ch==0)昇格が必要chになるのは些細なことですintが、実際にはこれはまったく必要ありません。オプティマイザーは、それ(int)chがゼロである場合にのみ、それがゼロであることを簡単に確認できchます。

したがって、実際の CPU パフォーマンスとさまざまな CPU フレーバーは、パフォーマンスについて考えるほど重要ではありません。オプティマイザーがまともな命令セットを見つけられるかどうかです。

于 2015-09-03T23:43:15.133 に答える