C/C++シフト演算子がアウトになった後の結果は予想できない

1705 ワード

論理シフト、算術シフトについては、迅雷深の大問題部分を参照してください.という質問がありました.
以前、C++標準では、シフト演算子(<<、>)がアウトになったときの動作は確定していませんでした.
The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.
私も当時この問題を深く研究したことがない.先日、あるネットユーザーからの手紙でこの件を聞いたところ、Intel CPUのシフト演算と関係があることに気づいた.次はそのネットユーザーからの手紙と私の返事です.
こんにちは.演算子<<はビット操作の効率的な操作として機能しますが、VC環境でよく分からない点を発見し、以下に表記するという問題に直面しました.
#include <stdio.h>
void main()
{
unsigned int i,j;
i=35;
//                ?
j=1<<i; // j 8
j=1<<35; // j 0
}

どこが正しいのか分からない.
理由はこうです:i=35;j=1<mov dword ptr [i],23h
mov eax,1
mov ecx,dword ptr [i]
shl eax,cl
mov dword ptr [j],eax
shlの文では、eax=1、cl=35です.一方、Intel CPUがshl命令を実行すると、clと31が先にand操作され、左シフトの回数が31以下であることが制限される.35&31=3なので,このような命令は1を3ビット左にシフトすることに相当し,結果は8である.
j=1<<35;1つは定数演算であり,VCは最適化を行わなくてもコンパイラは1<<35の結果を直接計算する.VCコンパイラは35が31より大きいことを発見すると,直接結果を0に設定する.この行のコードコンパイルによって生成されたマシン命令は、次のとおりです.
mov dword ptr [j],0
上記の2つの場合、VCコンパイラの最適化スイッチをオンにすると(例えばReleaseバージョンにコンパイル)、コンパイラは直接結果を0に設定します.
したがって,C/C++言語では,シフト動作が限界を超えないようにしなければ,結果は予想できない.
以下は、Intelドキュメントのshlコマンド制限シフト回数について説明します.
The destination operand can be a register or a memory location. The count operand can be an immediate value or register CL. The count is masked to 5 bits, which limits the count range to 0 to 31. A special opcode encoding is provided for a count of 1.
ソースドキュメント