网站建设 慕课,鹤壁市城乡一体化示范区,seo网站推广优化就找微源优化,一级a做爰片免费网站短视频播放前言 本篇分享的是部分操作符的概念与用法#xff0c;从经典例题入手#xff0c;带你快速了解和掌握。 收录专栏#xff1a;浅谈C语言 操作符详解下 10. 逗号表达式11. 下标引用、函数调用和结构成员12. 表达式求值12.1 隐士类型转换12.2 算术转换12.3 操作符的属性… 前言 本篇分享的是部分操作符的概念与用法从经典例题入手带你快速了解和掌握。 收录专栏浅谈C语言 操作符详解下 10. 逗号表达式11. 下标引用、函数调用和结构成员12. 表达式求值12.1 隐士类型转换12.2 算术转换12.3 操作符的属性 10. 逗号表达式
exp1,exp2,exp3,...expN逗号表达式就是用逗号隔开的多个表达式。 逗号表达式从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
//代码1
int main() {int a 1;int b 2;int c (a b, a b 10, a, b a 1);//逗号表达式printf(%d\n, c);//13return 0;
}//代码2
int main() {int a 1, b 3, c,d 0;if (a b 1, c a / 2, d 0); {printf(hello);//hello}return 0;
}11. 下标引用、函数调用和结构成员
[ ] 下标引用操作符 操作数一个数组名 一个索引值
int arr[10];//创建数组arr[9] 10;//实用下标引用操作符。[ ]的两个操作数是arr和9。( ) 函数调用操作符 接受一个或者多个操作数第一个操作数是函数名剩余的操作数就是传递给函数的参数。
#include stdio.hvoid test1(){printf(hehe\n);}void test2(const char *str){printf(%s\n, str);}int main(){test1(); //实用作为函数调用操作符。test2(hello bit.);//实用作为函数调用操作符。return 0;}访问一个结构的成员
. 结构体.成员名
- 结构体指针-成员名#include stdio.h
struct Stu
{char name[10];int age;char sex[5];double score;
};
void set_age1(struct Stu stu)
{stu.age 18;
}
void set_age2(struct Stu* pStu)
{pStu-age 18;//结构成员访问
}
int main()
{struct Stu stu;struct Stu* pStu stu;//结构成员访问stu.age 20;//结构成员访问set_age1(stu);pStu-age 20;//结构成员访问set_age2(pStu);return 0;
}12. 表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性决定。 同样有些表达式的操作数在求值的过程中可能需要转换为其他类型。
12.1 隐士类型转换
C的整型算术运算总是至少以缺省整型类型的精度来进行的。 为了获得这个精度表达式中的字符和短整型操作数在使用之前被转换为普通整型这种转换称为整型提升。 整型提升的意义 表达式的整型运算要在CPU的相应运算器件内执行CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度同时也是CPU的通用寄存器的长度。 因此即使两个char类型的相加在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。 通用CPUgeneral-purpose CPU是难以直接实现两个8比特字节直接相加运算虽然机器指令中可能有这种字节相加指令。所以表达式中各种长度可能小于int长度的整型值都必须先转换为int或unsigned int然后才能送入CPU去执行运算。 实例
char a,b,c;
...
a b c;b和c的值被提升为普通整型然后再执行加法运算。 加法运算完成之后结果将被截断然后再存储于a中。
如何进行整体提升呢 整形提升是按照变量的数据类型的符号位来提升的。
//负数的整形提升
char c1 -1;
变量c1的二进制位(补码)中只有8个比特位
1111111
因为 char 为有符号的 char
所以整形提升的时候高位补充符号位即为1
提升之后的结果是
11111111111111111111111111111111//正数的整形提升
char c2 1;
变量c2的二进制位(补码)中只有8个比特位
00000001
因为 char 为有符号的 char
所以整形提升的时候高位补充符号位即为0
提升之后的结果是
00000000000000000000000000000001//无符号整形提升高位补0整形提升的例子
//实例1
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中的ab要进行整形提升但是c不需要整形提升ab整形提升之后变成了负数所以表达式 a 0xb6b 0xb600 的结果是假但是c不发生整形提升则表达式 c0xb6000000 的结果是真。
运行结果 //实例2
int main()
{char c 1;printf(%u\n, sizeof(c));//1printf(%u\n, sizeof(c));//4printf(%u\n, sizeof(-c));//4return 0;
}实例2中的c只要参与表达式运算就会发生整形提升表达式 c就会发生提升所以 sizeof(c) 是4个字节。 表达式 -c 也会发生整形提升所以 sizeof(-c) 是4个字节但是 sizeof(c就是1个字节。
12.2 算术转换
如果某个操作符的各个操作数属于不同的类型那么除非其中一个操作数的转换为另一个操作数的类型否则操作就无法进行。下面的层次体系称为寻常算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int如果某个操作数的类型在上面这个列表中排名较低那么首先要转换为另外一个操作数的类型后执行运算。
注 算术转换要合理。 例如下面这段代码进行转换时精度会有丢失
float f 3.14;
int num f;//隐式转换会有精度丢失12.3 操作符的属性
复杂表达式的求值有三个影响的因素
操作符的优先级操作符的结合性是否控制求值顺序
两个相邻的操作符先执行哪个取决于他们的优先级。如果两者的优先级相同取决于他们的结合性。
操作符优先级
操作符描述用法聚组表达式函数调用rexprexp…,rexp[ ]下标引用rexp[rexp].访问结构成员lexp.member_name-访问结构指针成员rexp-member_name后缀自增lexp –后缀自减lexp –!逻辑反 !rexp~按位取反~ rexp单目表示正值 rexp-单目表示负值- rexp前缀自增 lexp–前缀自减– lexp*间接访问* rexp取地址 lexpsizeof取其长度以字节表示sizeof rexp sizeof(类型)(类型类型转换(类型) rexp*乘法rexp * rexp/ 除法rexp / rexprexp%整数取余rexp % rexp加法rexp rexp-减法rexp - rexp左移位rexp rexp右移位 rexp rexprexp大于rexp rexp大于等于rexp rexp小于rexp rexp小于等于rexp rexp等于rexp rexp!不等于rexp ! rexp位与rexp rexp^位异或rexp ^ rexp逻辑与rexp rexp? :条件操作符rexp ? rexp : rexp赋值lexp rexp以…加lexp rexp-以…减lexp - rexp*以…乘lexp * rexp/以…除lexp / rexp%以…取模lexp % rexp以…左移lexp rexp以…右移lexp rexp以…与lexp rexp^以…异或lexp ^ rexp逗号rexprexp
表达式的求值部分由操作符的优先级决定。
例如
a*b c*d e*f;这段代码在计算的时候由于 * 比的优先级高只能保证* 的计算是比 早但是优先级并不能决定第三个 * 比第一个 早执行。 所以表达式的计算机顺序就可能是
a*b
c*d
a*b c*d
e*f
a*b c*d e*f
//或者
a*b
c*d
e*f
a*b c*d
a*b c*d e*f的调用先后顺序无法通过操作符的优先级确定。
总结 我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径那这个表达式就是存在问题的。