C Language_Operator実際の戦闘_問題を解決するための演算子のいくつかの使用(説明)

1.一時変数を作成せずに2つの数値を交換します

ここにaとbの値を入力します。交換する一時変数tmpを作成することはできません。

最初:


#include<stdio.h>
int main()
{
    
    
	int a, b = 0;
	scanf("%d%d", &a, &b);
	a = a + b;
	b = a - b;//此时b=a+b-b=a
	a = a - b;//此时a=a+b-a=b实现了交换a ,b的目的
	printf("a=%d b=%d",a,b);
	return 0;
}

ここに画像の説明を挿入
(aとbが大きい場合、a + bの値がint型シェーピングの範囲を超え、a + bの値が失われるため、このアルゴリズムには問題があることに注意してください)

2番目のタイプ:

#include<stdio.h>
int main()
{
    
    
	int a, b = 0;
	scanf("%d%d", &a, &b);
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("a=%d b=%d",a,b);
	return 0;
}

ここに画像の説明を挿入
これはa = -1、b = 4の例です

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
交換を実現する

2.バイナリで1の桁数を見つけます

質問ソース

方法1:

数値%2は2進数を取得し、数値を2で割って次の桁を見つけます。

/ 2の後の最後の桁が0になるまで、falseの場合はループが停止します

#include<stdio.h>
int main()
{
    
    
	int count = 0;
	int n = 0;
	scanf("%d",&n);
	while (n)
	{
    
    
		if (n % 2 == 1)
			count++;
		n = n / 2;
	}
	printf("二进制位中1的个数为%d",count);
	return 0;
}

ここに画像の説明を挿入

しかし、ここに欠陥があり、負の数の2進数は計算できません

ここに画像の説明を挿入
余りが-1の場合、負の数%2はcount ++を実行しません

方法2:

&演算子を知っています

バイナリでは、1&0 = 0、1&1 = 1のみ

1コンピュータに保存されているのは000000000 ... 1

したがって、2進数&1を入力します

1を取得した場合、バイナリビットの最後のビットが1であり、変数>> 1であることを意味します。

次の2進数が0かどうかを確認するには、合計32回です。

#include<stdio.h>
int main()
{
    
    
	int a = 0;
	scanf("%d",&a);
	int count = 0;
	for (int i = 0; i < 32; i++)
	{
    
    
		int j = 1;
		if ((a & j) == 1)
		{
    
    
			count++;
		}
		a = a >> 1;
	}
	printf("二进制中1的个数%d",count);
	return 0;
}

ここに画像の説明を挿入

このとき、負のバイナリビット1の数も計算できます。

方法3:

ビット単位のAND演算に2つの隣接するデータを使用する

#include<stdio.h>
int main()
{
    
    
	int a = 0;
	scanf("%d",&a);
	int count = 0;
	while (a)
	{
    
    
		a = a & (a - 1);
		count++;
	}
	printf("二进制位为1的个数为%d",count);
	return 0;
}

ここに画像の説明を挿入
ここに画像の説明を挿入

a = 3の場合

aの2進数は01 1a
-1です
。2進数は01 0 -------- a&a-1は0 1 0(count = 1)

その後、aの2進数は0 1 0
------ a-1の2進数は00 1
-------------- a&a-1は0 0 0( count = 2)
この時点で、a = 0はループからの誤ったジャンプです。

バイナリビットに複数の1がある場合、同じバイナリビットが存在する必要があるため、a&(a-1)を0にすることはできません。

最後のビットが1の場合、a&a-1
の最後のビットは0になり、aに割り当てることは、ビットを移動することと同じです。最後のビットが0の場合、a&a-1の最後のビットは0であり、aに割り当てます。 Aを破棄するのと同じです

2進数に1が1つしかない場合、a&a-1は0でなければならず、カウントは1ずつ増加してループを離れます。最終的なカウントは、aの2進数1の数です。

3.2桁の2進数で異なる数の数を見つけます

質問ソース

まず、2進数には0と1の2つの状況があることがわかっています。

まず、排他的論理和演算を使用して、さまざまな数値を1に変更し、変数cに格納します。

変数cの2進数1の数を計算する際、ここでは2進数1の数は繰り返されません。

#include<stdio.h>
int main()
{
    
    
	int a = 0;
	int b = 0;
	scanf("%d%d",&a,&b);
	int c = a ^ b;
	int count = 0;
	for (int i = 0; i < 32; i++)
	{
    
    
		int j = 1;
		if ((c & j) == 1)
		{
    
    
			count++;
		}
		c = c >> 1;

	}
	printf("%d",count);
	return 0;
}

ここに画像の説明を挿入

4.発現評価

式の評価の一部は、演算子の優先順位と結合性の順に実行されます

優先度の高い方が先に計算されます。式の優先度が同じ場合、計算方向は結合法則に基づいているため、ここでは繰り返しません。

同時に、式のオペランドが他の型に変換される場合があります

シェーピング変換(非表示型変換)

例えば:

#include<stdio.h>
int main()
{
    
    
	char a = 3;
	char b = 137;
	char c = a + b;
	printf("%d",c);
	return 0;
}

ここに画像の説明を挿入
これは私たちが思っていたものではないことがわかりました140、

これは、char型のサイズが1バイトで、整数が4バイトであるためです。

char-8ビット、

int-32ビット、

整数の昇格は符号ビットに従って昇格されます。符号ビットはバイナリビットの最初のビットです。

+演算子はint型で動作するため、char型は最初に32ビットで埋められます

a = 0 0 0 0 0 0 1 1(補数、符号ビットは0)

a = 0000…01 1(32ビット)

b = 1 1 1 1 1 1 1 1(補数)

b = 0 0 0 0 0 0 1 1 1 1 1 1 1(32ビット)

a + b = 00…10 0 0 0 0 1 0(32ビット)

c = a + b(cは文字タイプであり、8ビットしか格納できないため、切り捨てが発生します)

c = 1 0 0 0 0 0 1 0

printf( "%d")なので、cを可塑化してプロモートする必要があります

cの符号ビットは1なので、1〜32ビットを追加します

整数昇格後のc

1 1 1 1 11…10 0 0 0 0 1 0(32ビット)(補数コード)
1 1 1 1 11…10 0 0 0 0 0 1(32ビット)(補数コード)
1 0 0 0 00…01 1 1 1 1 1 0(32ビット)(元のコード)

符号ビットが1の場合は、負の数であることを意味し
ます。元のコードは-116です。

一部の数値が符号なし桁の場合、整数の昇格はゼロを追加します。
整数の昇格は、2桁の数字があり、サイズがintよりも小さい場合にのみ発生します。

ここに画像の説明を挿入
整数昇格が発生しました。

これは、intからintより大きい型に変換する場合には発生せず、切り捨てられません。

コンピュータは式の計算において必ずしも一意ではありません

例えば:

           a*b+c*d+e*f

a b、c d、e * bを計算してから、3つを足し合わせることができます

または、全体としてb + c dを取り、最初に計算し、次にe * fを計算し、次にそれを合計します。

したがって、式の操作は必ずしも一意であるとは限らず、この状況を回避するように注意する必要があります。

例えば:int c=(++a)+(++a)+(++a);

#include<stdio.h>
int main()
{
    
    
	int a = 4;
	int c = (++a) + (++a) + (++a);
	printf("%d",c);

}

ここに画像の説明を挿入
ここでの計算は、最初に++ aを3回計算し、a = 7で、合計は21です。

ただし、コンパイラが異なれば計算順序も異なります。++ aを2回計算し(最初の2つの式全体を使用)、計算後に+(++ a)を計算することもできます。

計算式が複雑すぎるので、計算式に入る必要はありません。

おすすめ

転載: blog.csdn.net/dodamce/article/details/113243797