3

いくつかの調査を行った後、算術式で char と short が内部的に int に昇格されることがわかりました。しかし、そのような整数の昇格が割り当てで内部的に発生するかどうかはまだ疑問です。

(ですから、他の式に関するリンクだけを私に与えないでください。私は、ASSIGNMENT 式の内部で何が起こるかについて質問しています)

char ch1, ch2 = -1;
ch1 = ch2;  // Q

Q: 次のうち、社内で発生するのはどれですか?

1、ch1 の値がそのまま ch2 に代入されます。ここでは整数の昇格は行われません。

2, ch1の値をまずint型に昇格(8ビット→32ビット)し、32ビットの値をchar型の8ビットに降格して最終結果。整数の昇格はここで行われます。

私はこの本を見つけました: C Primer Plusの 174 ページには:

「...式に現れると、char と short は、signed と unsigned の両方で、自動的に int に変換されるか、必要に応じて unsigned int に変換されます...」

だから私はそれが 2 であるべきだと思いますが、整数昇格が起こらない 1 であるべきだと誰かが私に言ったのを聞いたことがあります。

私は本当に混乱しています。私を手伝ってくれますか?前もって感謝します。

4

4 に答える 4

3

C99 標準から:

6.5.16.1 簡単な代入

2 単純代入 (=) では、右オペランドの値が代入式の型に変換され、左オペランドで指定されたオブジェクトに格納されている値が置き換えられます。

あなたの場合、LHS と RHS の両方が同じ型であるため、変換の必要はありません。

于 2015-10-26T03:55:12.533 に答える
2

答えは1でも2でもない。

ch2 の値がそのまま ch1 に代入されます。代入演算子では、左側のオペランドがターゲットです。

プロモーションはありません。動作は C11 6.5.16.1/2 で指定されています。

単純代入 ( =) では、右オペランドの値が代入式の型に変換され、左オペランドで指定されたオブジェクトに格納されている値が置き換えられます。

前の段落では、次のように定義されています。

代入式の型は、左辺値変換後の左オペランドの型です。

ここで、「左辺値変換」とは、左辺値から右辺値への変換を意味し、型のconstvolatileおよび_Atomic修飾子を削除する効果があります。(配列型にも影響がありますが、配列は代入の左オペランドとして表示できないため、ここでは意味がありません)。

「C Primer Plus」からのあなたの引用は本による間違いです。整数昇格は、すべての式で発生するわけではありません。実際、整数が演算子のオペランドであり、その演算子の定義で、そのオペランドが整数昇格を受けることが指定されている場合に発生します

ほとんどの演算子はそれを指定しますが、代入演算子などは指定しsizeofません。各演算子の C 標準の仕様を調べて、その演算子がそのオペランドをプロモートするかどうかを確認できます。

于 2015-10-26T05:39:17.897 に答える
1

@chux のコメントにあるように、これがどのように懸念されるのかわかりません。すべてが内部で発生するため、ブラック ボックスとして扱う必要があり、そのような動作に依存するべきではありません。

しかし、好奇心が強いので、スニペットを取得してアセンブリにコンパイルしました。正確に何が起こっているのか見てみましょう!

これはソース C コードです。というファイルに保存しましたtest.c

int main() {
  char ch1 = -1;
  char ch2 = -1;
  ch1 = ch2;
}

そして、これが gcc によって生成されたアセンブリです。を呼び出すことで、自分で生成できますgcc -S test.c。以下は関連するセクションです。

...

    movb    $-1, -1(%rbp)
    movb    $-1, -2(%rbp)
    movb    -2(%rbp), %cl
    movb    %cl, -1(%rbp)
    popq    %rbp

...

基本的に、値 -1 をスタックに 2 回プッシュし ( %rbp)、2 番目のスロットに格納されている値ch2を別の一時レジスタ%clに移動し ( )、最後に最初のスロットに割り当てch1ます。

待って、この一時的なレジスター ビジネスは何ですか。%cl サイズがちょうど 1 バイトであることがわかりました。はい、変換は行われません。

余談ですが、アセンブリに至るまで、格納するのに十分なスペースがない限り、型変換のようなものはありません。たとえば、値を -1 から、たとえば 65537 (short を超えるだけ) に変更すると、次のようになります。

x = 65537;

になります:

movl    $65537, -4(%rbp)

変数 x のスタックに 4 バイトを割り当てるだけです。したがって、内部的には、昇格は単にスタック上により多くのスペースを割り当てることです。整数を char に降格すると、整数から最後のバイトを取得して、スタックの新しいスロットに貼り付けます。したがって、両方が最初から char である場合 (両方ともスタックに 1 バイト スロットが割り当てられている)、実際に変換する必要はありません。もちろん、これはコンパイラに依存します。ch2サイズが 1 MB のスタックに実際にプッシュし、 の階乗を計算しch1、歌を歌い、次に を割り当てるch1、非常に非効率なコンパイラを使用できますch2。冒頭で述べたように、これはブラック ボックスとして扱い、当てにしないでください。

于 2015-10-26T03:52:28.630 に答える