演算子の詳しい説明(2)

9. 条件演算子

疑問符とコロンで構成され、3 つの式と 3 つの演算子があるため、条件演算子が唯一の三項演算子となり、 exp1 は true、exp2 は計算され、exp3 はカウントされず、式全体の結果は exp2 の結果になります。exp1 は false、exp2 は計算されません、exp3 は計算され、式全体の結果は exp3 の結果になります。

exp1 ? exp2 : exp3

2 つのコードの効果は同じであり、条件演算子の使用です。 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int m = 0;

	m = (a > b ? a : b);

	printf("%d\n", m);

	return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int m = 0;

	if (a > b)
		m = a;
	else
		m = b;

	printf("%d\n", m);

	return 0;
}

10. カンマ式

exp1, exp2, exp3, …expN

カンマ式は、カンマで区切られた複数の式です。
カンマ式は左から右に順番に実行されます。式全体の結果は、最後の式の結果になります。

int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, a, b = a + 1);
	printf("c=%d\n", c);
	return 0;
}

  

11. 添字参照、関数呼び出し、構造体メンバー

1. [ ] 添字参照演算子

オペランド: 配列名 + インデックス値

int arr[10];//配列を作成します
arr[9] = 10;//実用的な添字参照演算子。
[ ] の 2 つのオペランドは arr と 9 です。

2. ( ) 関数呼び出し演算子

1 つ以上のオペランドを受け入れます。最初のオペランドは関数名で、残りのオペランドは関数に渡されるパラメーターです。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void test1()
{
	printf("hehe\n");
}
void test2(const char* str)
{
	printf("%s\n", str);
}
int main()
{
	test1();
	test2("hello bit.");
	return 0;
}

3. 構造体のメンバーへのアクセス

. 结构体.成员名
-> 结构体指针->成员名

これは構造体メンバーアクセス演算子の使用法です。 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct Book
{
	char name[20];
	int price;
};
//结构体变量.成员
//结构体指针->成员

void Print(struct Book* pb)
{
	printf("%s %d\n", (*pb).name, (*pb).price);
	printf("%s %d\n", pb->name, pb->price);
}

int main()
{
	struct Book b = {"C语言指南", 55};
	printf("%s %d\n", b.name, b.price);

	Print(&b);

	return 0;
}

12. 式の評価

式が評価される順序は、演算子の優先順位と結合性によって部分的に決まります。
同様に、一部の式のオペランドは、評価中に他の型に変換する必要がある場合があります。

12.1 暗黙的な型変換

C の整数算術演算は常に、少なくともデフォルトの整数型の精度で実行されます。この精度を実現するために、式内の文字および短整数のオペランドは、使用前に単純な整数型に変換されます。この変換は、整数プロモーション
と呼ばれます整数昇格の重要性:

式の整数演算は、CPU の対応する演算デバイスで実行する必要があります。CPU の整数演算器 (ALU) のオペランドのバイト長は、一般的に int のバイト長ですが、int のバイト長でもあります
。 CPUの汎用レジスタです。
したがって、2 つの char 型の加算が実際に CPU によって実行される場合でも、最初に CPU の整数オペランドの標準長に変換する必要があります

汎用 CPU (汎用 CPU) では、8 ビット 2 バイトを直接加算することは困難です (
機械語命令にはそのようなバイト加算命令があるかもしれませんが)。したがって、長さが int の長さよりも小さい可能性がある式内のさまざまな整数値は、
計算のために CPU に送信される前に int または unsigned int に変換する必要があります。

a と b の値は、加算演算が実行される前に通常の整数に変換されます。
 加算が完了すると、結果は c に格納される前に切り捨てられます。

全体的な改善をどのように実行するか?
整数昇格は、変数のデータ型の符号ビットに従って昇格されます。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//int - signed int
//unsigned int 
//char 到底是signed char还是unsigned char是不确定的,C语言标准没有明确指定,是取决于编译器的
//在当前使用的VS上,char == signed char
int main()
{
	char a = 5;
	//00000000000000000000000000000101
	//00000101-存进去的是这8个bit位
	char b = 126;
	//00000000000000000000000001111110
	//01111110
	char c = a + b;
	//00000000000000000000000000000101-a
	//00000000000000000000000001111110-b
	//00000000000000000000000010000011
	//10000011-c里面只能放这8个bit位
    //按照符号位整形提升
	//11111111111111111111111110000011
	//10000000000000000000000001111100
	//10000000000000000000000001111101
	//-125
	printf("%d\n", c);

	return 0;
}

 整形強化の例:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	char a = 0xb6;
	short b = 0xb600;
	int c = 0xb6000000;
	if (a == 0xb6)
		printf("a");
	if (b == 0xb600)
		printf("b");
	if (c == 0xb6000000)
		printf("c");
	return 0;
}

  

例 1 では、a と b はプラスチックによってアップグレードされる必要がありますが、c はプラスチックによってアップグレードされる必要はありません。a
と b がプラスチックによってアップグレードされると負の数になるため、式 a==0xb6 とb==0xb600 は false ですが、c は false です。プラスチック プロモーションが発生した場合、式 c==0xb6000000 の結果は true になります。

12.2 算術変換

演算子のオペランドの型が異なる場合、一方のオペランドが他方のオペランドの型に変換されない限り、操作は続行できません。以下の階層は通常の算術変換と呼ばれます。

long double
double
float
unsigned long int
long int
unsigned int
int

オペランドの型が上記のリストの下位にランクされている場合、まず演算を他のオペランドの型に変換する必要があります。
警告:
ただし、算術変換は合理的でなければなりません。そうしないと、潜在的な問題が発生します。

float f = 3.14;
int num = f;//隐式转换,会有精度丢失

12.3 演算子のプロパティ

複雑な式の評価に影響を与える要因は 3 つあります。
 1. 演算子の優先順位
 2. 演算子の結合性
 3. 評価順序を制御するかどうか。
隣接する 2 つの演算子のうちどちらが最初に実行されますか? 優先順位によって異なります。両方の優先度が同じ場合、それは結合性によって異なります。
演算子の優先順位

演算子
_
説明する 使用例 結果のタイプ 組み合わせ 評価の順序を制御するかどうか
() グループ (表現) 表現と
同じ
該当なし いいえ
() 関数呼び出し rexp(rexp,...,rexp) レックス LR いいえ
[ ] 添え字参照 表現[表現] レクプ LR いいえ
構造体のメンバーにアクセスする lexp.メンバー名 レクプ LR いいえ
-> アクセス構造体ポインタメンバー rexp->member_name レクプ LR いいえ
++ サフィックスの増分 lexp++ レックス LR いいえ
-- サフィックスのデクリメント lexp -- レックス LR いいえ
論理逆 レックス レックス RL いいえ
ビットごとの反転 ~ レックス レックス RL いいえ
+ 単眼、正の値を示す +rexp レックス RL いいえ
- 単眼、負の値を表す - レックス レックス RL いいえ
++ プレフィックスの増分 ++ レクプ レックス RL いいえ
-- プレフィックスデクリメント -- レクプ レックス RL いいえ
* 間接アクセス * レックス レクプ RL いいえ
& 住所を取る &レクプ レックス RL いいえ
のサイズ その長さをバイト単位で取得し
ます
sizeof reexp sizeof(type
)
レックス RL いいえ
(
タイプ)
型変換 (タイプ) rexp レックス RL いいえ
* 乗算 rexp * rexp レックス LR いいえ
/ 分割 レックス / レックス レックス LR いいえ
% 整数の剰余 reexp % reexp レックス LR いいえ
+ 追加 表現力 + 表現力 レックス LR いいえ
- 引き算 レックス - レックス レックス LR いいえ
<< 左方移動 rexp << rexp レックス LR いいえ
>> 右シフト レクプ >> レクプ レックス LR いいえ
> 以上 rexp > rexp レックス LR いいえ
>= 以上 rexp >= rexp レックス LR いいえ
< 未満 rexp < rexp レックス LR いいえ
<= 以下 rexp <= rexp レックス LR いいえ
演算子
_
説明する 使用例 結果のタイプ 組み合わせ 評価の順序を制御するかどうか
== 等しい rexp == rexp レックス LR いいえ
!= 不等于 rexp != rexp rexp L-R
& 位与 rexp & rexp rexp L-R
^ 位异或 rexp ^ rexp rexp L-R
| 位或 rexp | rexp rexp L-R
&& 逻辑与 rexp && rexp rexp L-R
|| 逻辑或 rexp || rexp rexp L-R
? : 条件操作符 rexp ? rexp : rexp rexp N/A
= 赋值 lexp = rexp rexp R-L
+= 以...加 lexp += rexp rexp R-L
-= 以...减 lexp -= rexp rexp R-L
*= 以...乘 lexp *= rexp rexp R-L
/= 以...除 lexp /= rexp rexp R-L
%= 以...取模 lexp %= rexp rexp R-L
<<= 以...左移 lexp <<= rexp rexp R-L
>>= 以...右移 lexp >>= rexp rexp R-L
&= 以...与 lexp &= rexp rexp R-L
^= 以...异或 lexp ^= rexp rexp R-L
|= 以...或 lexp |= rexp rexp R-L
逗号 rexp,rexp rexp L-R

我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题
的。


今天的分享到这里就结束啦!谢谢老铁们的阅读,让我们下期再见。

おすすめ

転載: blog.csdn.net/2301_79035870/article/details/132428577