1.算術演算子
+ - * / %
注意:
%
演算子の両方のオペランドは整数でなければなりません。- 残りのいくつかの演算子は、整数および浮動小数点数に使用できます。
- 以下のために
/
、両方の数値が整数である場合、オペレータ、その後、整数除算を実行する1つの浮動小数点数である場合に、浮動小数点除算を行います。
2.シフト演算子
- 論理シフト:バイナリビットが左右にシフトされ、両端が0で補われるため、符号ビットを気にする必要はありません。
- 算術シフト:バイナリビットが左右にシフトされ、両端が0で補完されますが、符号ビットは変更しないでください。
アセンブリに4つの命令を導入:
SHL:論理的に左
シフトSHR:論理的に右
シフトSAL:左シフト算術
SAR:右シフト算術
int main()
{
char i = 128;
i = i >> 3;
printf("%d\n", i);
return 0;
}
上記のコードブロックは、論理右シフトまたは算術右シフトを使用していますか?
1.符号付き整数正数左シフト
int main()
{
int i = 1;
i = i << 3;
return 0;
}
ここではvs2017を使用して、逆アセンブリウィンドウを開きます
。使用したロジックは左シフトです。
2.符号なし整数正数左シフト
int main()
{
unsigned int i = 1;
i = i << 3;
return 0;
}
使用されるロジックは左シフトです。
3.符号付き整数の負の数の左シフト
int main()
{
int i = -1;
i = i << 3;
return 0;
}
使用されるロジックは左シフトです。
4.符号なし整数負数左シフト
int main()
{
unsigned int i = -1;
i = i << 3;
return 0;
}
使用されるロジックは左シフトです。
結論:符号型、正の数、負の数のいずれがあるかに関係なく、左にシフトすると、論理的に左にシフトします。
5.符号付き整数正数シフト右
int main()
{
int i = 1;
i = i >> 3;
return 0;
}
使用される演算は右シフトされます。
6.符号なし整数正数右シフト
int main()
{
unsigned int i = 1;
i = i >> 3;
return 0;
}
論理右シフトが使用されます。
7.符号付き整数負数右シフト
int main()
{
int i = -1;
i = i >> 3;
return 0;
算術右シフトが使用されます。
8.符号なし整数負数右シフト
int main()
{
unsigned int i = -1;
i = i >> 3;
return 0;
}
論理右シフトが使用されます。
結論:符号付きの数値の場合は、右にシフトするときに算術右シフトを使用し、符号のない数値の場合は、右にシフトするときに論理右シフトを使用します。
注:この場合、符号なしの数値ですが、最上位ビットは1であり、符号付きとみなされ、算術右シフトが使用されますが、右シフトの場合、左に0が追加されます。
int main()
{
unsigned char i = 128;
i = i >> 3;
printf("%d", i);
return 0;
}
結果は次のとおりです。
なぜ左シフトがすべて論理左になるのですか。
回答:最初に、さまざまな数値がバイナリに格納される方法を理解します。
正の数はプリミティブバイナリに格納されます。3などのように、0x3としてコンピューターに格納されます。
負の数は、コンピューターに0xfffffffbとして格納される-3などの補数に従ってコンピューターに格納されます。
コンピュータは負の数を補数の形で保存します。符号なしの数値が左にシフトされる場合、その符号ビットは変更されないため、論理左シフトが使用されます。ただし、右にシフトされる場合、右にシフトされる符号なしの数値は符号ビットを変更せず、符号付きの数値は符号ビットは変更されないため、算術右シフトのみを使用できます。
左にシフトすることは2を乗算することと同じです。
右にシフトすることは2で除算することと同じ
です。左に
シフトすることは値を変更しません。シフトは乗算と除算よりも優れています。高速です。
3.ビット演算子
&//ビットごとのAND
| //ビットごとのOR
^ //ビットごとのXOR
オペランドは整数でなければなりません。
より興味深い質問:メモリに格納されているバイナリ1の数を整数で見つけますか?
- 一般的な考え方は、ループを行い、数値を1つずつ右にシフトし、1&で数えることです。内部のメソッドは32回ループする必要があり、最適化できます。最初にこのコードを添付します:
int main()
{
int num = 99;
int i = 0;
int count = 0;//计数
for (; i < 32; i++)
{
if (1 == ((num >> i) & 1))
{
count++;
}
}
printf("%d\n", count);
return 0;
}
2.もう1つの難しいアイデア:ループを実行し&
、数値を1から1を引いた値に等しくします。
1回目:カウント+1
2回目:カウント+1
3回目:カウント+1
4回目:カウント+1
最後に、数は0で、ループは停止し、数は2進数で4つになります。
添付コード:
int main()
{
int num = 99;
int count = 0;//计数
while (num)
{
count++;
num = num & (num - 1);
}
printf("%d\n", count);
return 0;
}
結果は次のとおりです。
4.代入演算子
- 複合演算子
+ =
-=
* =
/ =
%=
>> =
<< =
&=
| =
^ =
注:このような方程式もすべて右から左に表示されます。
といった:
int main()
{
int a = 3;
int i = 10;
int j = 20;
a *= i + j;
printf("%d\n", a);
return 0;
}
出力結果は90です。
5.単項演算子
! 逻辑反操作
-
+
& 取地址
sizeof 操作数的类型长度(字节为单位)(不是函数)
~ 按二进制位进行取反
- -
++
*
(类型) 强制类型转换
注:変数は、変数スペース、変数コンテンツ、変数アドレスの 3つの観点から理解できます。
変更されたのは、データの表示方法です。
タイプは、変数の意味、変数の表示方法、開いているスペースの量を決定します。
6.関係演算子
>
>=
<=
!=
==
7.論理演算子
&&
||
注:
論理AND:前半が確立されていない場合は、後半を実行する必要はありません。
論理OR:前半が確立されている場合、後半を実行する必要はありません。
8.条件操作符
三項演算子とも呼ばれます
たとえばa>b?a:b
、aがbより大きい場合はaを出力し、それ以外の場合はbを出力することを意味します。
9.カンマ式
コンマ式では、コンマの内容が順番に実行され、最後の式が式の値として使用されます。
int main()
{
int b = (1, 2, 3, 4, 5, 6, 7, 8);
printf("%d\n", b);
return 0;
}
最終結果は、b = 8です。
演算子の優先順位と結合性。
通常、特に複雑な式は記述しないでください。
暗黙的な型変換:
整数の昇格が必要なのはなぜですか?
式の計算は、CPUの対応する演算デバイスで実行されるため、CPU整数演算ユニット(ALU)のオペランドのバイト長は、通常、intのバイト長であり、CPUの汎用レジスターの長さでもあります。
整数昇格を実行するにはどうすればよいですか?
積分の昇格は、変数のデータ型の符号ビットに従って昇格されます。
①符号なしの数値の場合:整数昇格は、すべての0を直接補完します。
②符号付きの場合:符号ビットを補います(変数型参照)。
数値はchar型であり、演算子で操作すると整数の昇格が発生します。