镇江网站建设,建设城市2的游戏在哪个网站,盗版小说网站怎么做,中国建筑招聘提示#xff1a;本篇内容是C语言操作符详解下篇 文章目录前言八、条件表达式九、逗号表达式十、 下标引用、函数调用和结构成员1. [ ] 下标引用操作符2. ( ) 函数调用操作符3.结构成员访问操作符十一、表达式求值1. 隐式类型转换举例说明1举例说明2举例说明32.算数转换3.操作… 提示本篇内容是C语言操作符详解下篇 文章目录前言八、条件表达式九、逗号表达式十、 下标引用、函数调用和结构成员1. [ ] 下标引用操作符2. ( ) 函数调用操作符3.结构成员访问操作符十一、表达式求值1. 隐式类型转换举例说明1举例说明2举例说明32.算数转换3.操作符的属性前言
八、条件表达式 表达式1为真,执行表达式2,否则执行表达式3
#define _CRT_SECURE_NO_WARNINGS 1
#includestdio.h
int main() {int a 0;int b 0;scanf(%d, a);a 5 ? (b 3) : (b -3);printf(%d\n, b);}int main() {int a 0;int b 0;scanf(%d %d, a, b);int m (a b ? a : b);printf(%d\n, m);
}九、逗号表达式 逗号表达式就是用逗号隔开的多个表达式。 逗号表达式从左向右依次执行。整个表达式的结果是最后一个表达式的结果
int main() {int a 1;int b 2;int c (a b, a b 10, a, b a 1);//逗号表达式printf(%d\n, c);
}十、 下标引用、函数调用和结构成员
1. [ ] 下标引用操作符
操作数一个数组名 一个索引值
2. ( ) 函数调用操作符
接受一个或者多个操作数第一个操作数是函数名剩余的操作数就是传递给函数的参数
#includestring.h
int Add(int x, int y) {return x y;
}
int main() {int len strlen(abc);//()函数调用操作符printf(%d\n, len);int c Add(3, 5);//Add,3,5都是()操作数//test();//调用函数时()的操作数只有一个,是函数名return 0;
}3.结构成员访问操作符 struct S {int num;char c;
};
void test(struct S* ps) {printf(%d\n, (*ps).num);printf(%d\n, (*ps).c);//- 结构成员访问操作符//结构体指针-结构体成员printf(%d\n, ps-num);printf(%c\n, ps-c);
}
int main() {struct S s { 100,b };//结构体初始化成员使用{}//打印结构体中的成员数值printf(%d\n, s.num);printf(%c\n, s.c);//操作符 结构体变变量.结构体成员名test(s);
}十一、表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性决定。 同样有些表达式的操作数在求值的过程中可能需要转换为其他类型。
1. 隐式类型转换
C的整型算术运算总是至少以缺省整型类型的精度来进行的。(缺省整型就是默认整型int) 为了获得这个精度表达式中的字符和短整型操作数在使用之前被转换为普通整型这种转换称为整型提升。 b和c的值被提升为普通整型然后再执行加法运算 加法运算完成之后计算之后的结果也是整型,但是a是char类型, 结果将被截断然后再存储于a中 整型提升的意义(整形提升只针对char和short) 适用CPU的通用寄存器的长度
举例说明1
int main() {char a 3;//00000000 00000000 00000000 00000011 int 类型的3的补码//char类型只有存储1个字节(8个bit位)的数据 00000011---截断char b 127;//00000000 00000000 00000000 01111111 127的补码//01111111----截断char c a b;//00000011//01111111//整形提升//整形提升是按照变量的数据类型的符号位来提升的//提升之后://00000000 00000000 00000000 00000011//00000000 00000000 00000000 01111111//相加后的结果://00000000 00000000 00000000 10000010//c的类型是char,结果截断之后为:10000010//提升之后的补码:11111111 11111111 11111111 10000010//反码:11111111 11111111 11111111 10000001//原码:10000000 00000000 00000000 01111110//-126printf(%d\n, c);return 0;}解释: 1.计算的时候用补码来计算 2.short类型和char类型的两个数相加时要进行整形提升 3.整形提升是按照变量的数据类型的符号位来提升的 4.计算之后得到整形提升之后的补码,但是由于接收结果的类型是char类型,只能存储一个字节的数据(8个比特位),所以要截断,截断之后的8个比特位就是接收结果的变量的值 但是打印结果c的时候,char类型的数据要以%d的形式打印出来,这时候还要进行整形提升,提升之后的是它的补码,%d打印出来结果的值是原码
举例说明2
int main()
{//char类型的取值范围是:-128到127char a 0xb6;//b6: 1011 0110short b 0xb600;int c 0xb6000000;if (a 0xb6)printf(a);if (b 0xb600)printf(b);if (c 0xb6000000)printf(c);return 0;
}解释: 1.0x开头的是16进制的数字. 2.不打印a,b的解说一: a在执行时,b6整形提升的时候最高位是1,前面都补1,结果一定不等于0xb6,所以不会打印a;同理变量b最高位是1,整形提升的时候最高位是1,前面都补1,结果一定不等于0xb600,所以不会打印b 不打印a,b的解说二: 16进制0xb6的数值是182,但是char类型的取值范围是-128到127,放不了182,所以a肯定不会和0xb6相等.b同理
3.但是对于c来说是int类型的数据,不需要整形提升,所以c可以打印出来
a,b要进行整形提升,但是c不需要整形提升 a,b整形提升之后,变成了负数,所以表达式 a 0xb6 , b 0xb600 的结果是假,但是c不发生整形提升,则表 达式 c0xb6000000 的结果是真.
举例说明3 int main()
{char c 1;char d2;printf(%u\n, sizeof(c));printf(%u\n, sizeof(c));printf(%u\n, sizeof(-c));printf(%u\n,sizeof(cd));return 0;
}解释: 1.sizeof©算的是char类型变量的大小,结果为1 2.c,-c也是表达式,计算的时候也要进行整形提升,结果算的是int类型变量的大小,结果为4 3.char类型和char类型相加的时候都要进行整形提升,提升之后的结果还是整形,sizeof(cd)结果是4 4.c只要参与表达式运算,就会发生整形提升,表达式 c ,就会发生提升,所以 sizeof(c) 是4个字节. 表达式 -c 也会发生整形提升,所以 sizeof(-c) 是4个字节,但是 sizeof© ,就是1个字节 5.%u打印输出无符号数 2.算数转换
如果某个操作符的各个操作数属于不同的类型那么除非其中一个操作数的转换为另一个操作数的类型否则操作就无法进行。下面的层次体系称为寻常算术转换 下面没有讨论char和short,因为char和short类型的数据在计算的时候要整形提升. 如果某个操作数的类型在上面这个列表中排名较低那么首先要转换为另外一个操作数的类型后执行运算。
3.操作符的属性
复杂表达式的求值有三个影响的因素: (1)操作符的优先级 (2)操作符的结合性 (3)是否控制求值顺序 两个相邻的操作符先执行哪个? 取决于他们的优先级,如果两个的优先级相同,取决于他们的结合性. 通过上表发现: 控制执行顺序的有四个: || ? : , 所以上式有两个计算顺序: 注意:同上操作符的优先级只能决定自减–的运算在的运算的前面但是我们并没有办法得知操作符的左操作数的获取在右操作数之前还是之后求值所以结果是不可预测的是有歧义的。
//代码3-非法表达式
int main()
{int i 10;i i-- - --i * ( i -3 ) * i i;printf(i %d\n, i);return 0;
}代码3在不同编译器中测试结果非法表达式程序的结果
//代码4
int fun()
{static int count 1;return count;
}
int main()
{int answer;answer fun() - fun() * fun();printf( %d\n, answer);//输出多少return 0;
}这个代码有没有实际的问题 有问题 虽然在大多数的编译器上求得结果都是相同的。但是上述代码 answer fun() - fun() * fun(); 中我们只能通过操作符的优先级得知先算乘法再算减法。
函数的调用先后顺序无法通过操作符的优先级确定
尝试在linux 环境gcc编译器,VS2013环境下都执行看结果
//代码5
#include stdio.h
int main()
{int i 1;int ret (i) (i) (i);printf(%d\n, ret);printf(%d\n, i);return 0;
} VS2013环境的结果 寄存器:(计算机里面的存储器) ebp,esp 一般用来存放地址 eax ebx ecx edx
看看同样的代码产生了不同的结果这是为什么 简单看一下汇编代码.就可以分析清楚. 这段代码中的第一个 在执行的时候第三个是否执行这个是不确定的因为依靠操作符的优先级和结合性是无法决定第一个 和第 三个前置 的先后顺序。
总结我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径那这个表达式就是存在问题的。 结语:C语言操作符的讲解已全部结束.你是否有所收获呢小伙伴们?记得点赞收藏博客关注后续的C语言内容哦~