栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【操作符:编程小白与C语言正式建交的第四天(打地基阶段4)】

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【操作符:编程小白与C语言正式建交的第四天(打地基阶段4)】

算术操作符 +       -      *      /      % 1、除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。 2、 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。 3、 % 操作符的两个操作数必须为整数。返回的是整除之后的余数。 移位操作符

注:他们的操作数必须是整数。

先铺垫一些基础知识:

计算机中一个整数的二进制有3种表示形式:原码、反码、补码,由于是整型,因此大小为四个字节,可以用32个bit位来表示,其中,最左边一位是符号位,0表示正数,1表示负数

例如:

3的原码:00000000000000000000000000000011

-5的原码:10000000000000000000000000000101

正整数:原码反码补码三者相同

例如

3的反码:00000000000000000000000000000011

3的补码:00000000000000000000000000000011

负整数:需要通过计算相互求得:原码除符号位不变,其他各位取反得到反码,反码加1得到补码

例如:

-5的反码:11111111111111111111111111111010

-5的补码:11111111111111111111111111111011

内存中:二进制数是以补码的形式存在,因此在移位时也自然是针对补码进行,因此对负整数操作时一定要注意!!

<< 左移操作符

移位规则:左边丢弃,右边补0

 由上述代码可知:左移有乘2的效果,每左移一位,原结果就乘一次2

>> 右移操作符

移位规则:

算数移位:右边丢弃,左边补原符号位(vs编译器中采用的就是算数移位)

逻辑移位:右边丢弃,左边补0(大部分编译器不是采用逻辑移位,因此这种情况少见)

警告⚠ : 对于移位运算符,不要移动负数位,这个是标准未定义的,也可说就是错的。 例如: int num = 10 ; num >>- 1 ; //error

位操作符

注:他们的操作数必须是整数。

& //按位与 | //按位或 ^ //按位异或 对它们的补码进行按位操作

*按位异或的一个实际应用:不创新变量的前提下,交换两变量内容 先来看一下基础: 3的2进制表示为:011 011^011=0——>3^3=0 5的2进制表示为:101 101^000=101——>5^0=5 结论一;一个数和自己本身异或,结果为0,一个属与0异或,结果为本身。 3^3^5=5; 3^5^3=5; 结论二:异或运算满足交换律 由此可实现题目要求的功能,见如下代码:

下面这一种方法虽然也可以实现,但是当a,b两个数都很大的时候,两数相加会出现栈溢出,因此上面的一种方法更好

  • 练习一(左移和按位与的综合应用):编写代码实现:求一个整数存储在内存中的二进制(即该数的补码)中1的个数

方法:将1依次左移,直至移到第32位(移31次),每移动一次,和原数进行一次按位与运算,如果结果不为0(为真),则此位上为1,否则为0,再利用for循环计数即可,具体代码如下:

 赋值操作符

计算顺序是从右往左,把右边的值赋给左边

==

复合赋值符:+=    -=    *=    /=    %=    >>=    <<=    &=    |=    ^=

 int x = 10;

 x = x+10;

 x += 10 ; //复合赋值,与  x = x + 10 ;等价。 其他运算符一样的道理。这样写更加简洁。 单目操作符 !   逻辑反操作
int main()  //C语言中0表示假,非0表示真
{
	int flag = 3;
	//flag为真,进入if
	if (flag)
	{}
	
	//flag为假,进入if
	if(!flag)
	{}

	return 0;
}
-           负值 +           正值 &           取地址

&a表示的是a的地址,如果要定义一个变量来存放地址时,应该定义为指针变量,指针变量里放的都是对应变量的地址

%d打印的是整数,地址要用%p打印

 sizeof      操作数的类型长度(以字节为单位)

 计算类型所创建的变量占据空间的大小,也可直接计算变量所占空间的大小,单位是字节

也可以应用于数组用于计算数组中元素个数

应用于变量时可以省略括号(侧面说明它不是函数),但应用于类型时不能省略 

sizeof()与数组

 数组在函数传参时传的是首元素的地址,此时sizeof(arr)计算的是地址的长度,在*86环境下,地址长度是4,因此若要使用sizeof来实现计算元素个数,最好在主函数中计算出来,然后将其作为参数一并传参

~           对一个数的二进制补码按位取反

--          前置、后置-- ++          前置、后置++

前置:先++(--)后使用

后置;先使用,后++(--)

//++和--运算符
//前置++和--
#include 
int main()
{
	int a = 10;
	int x = ++a;
	//先对a进行自增,然后对使用a,也就是表达式的值是a自增之后的值。x为11。
	int y = --a;
	//先对a进行自减,然后对使用a,也就是表达式的值是a自减之后的值。y为10;
	return 0;
}
//后置++和--
#include 
int main()
{
	int a = 10;
	int x = a++;
	//先对a先使用,再增加,这样x的值是10;之后a变成11;
	int y = a--;
	//先对a先使用,再自减,这样y的值是11;之后a变成10;
	return 0;
}
*           间接访问操作符(解引用操作符)

*和&搭配在有指针的情况下使用

int main()
{
	int a = 10;
	int* p = &a;
	*p = 10;//*p=a
	printf("%dn", a);

	return 0;
}
(类型)       强制类型转换

例如:

srand((unsigned int)time(NULL))中,time()函数的返回值类型是time_t,但srand()函数要求参数的类型是unsigned int,因此在前面加上(unsigned int),将time_t类型强制转换为unsigned int类型

关系操作符 >    >=    <    <=    != (用于测试“不相等” )   ==  ( 用于测试“相等”) 比较简单,但要注意以下陷阱: 1. 在编程的过程中 == 和 = 不小心写错,导致的错误 2.测试字符串内容是否相同时,不能用==,即"abc" == "abcdef"这种写法是错误的,这比的是两字符串首元素地址是否相等,应该用专门的函数strcmp()使用时记得引用头文件string.h 逻辑操作符 &&逻辑与

两数相与,同时为真,结果才真,只要有一个为假,结果为假

||  逻辑或

两数相或,同时为假,结果才假,只要有一个为真,结果为真

C语言中,0为假,非0为真

注意区分逻辑与和按位与的特点!!!

练习一:360的一道面试题

 结论:

1.对于&&来说,只要左边为0,便可以判断结果为0,就不再进行之后的运算

2.对于||来说,只要左边为非0,便可以判断结果为1,就不再进行之后的运算 条件操作符 exp1 ? exp2 : exp3

其实是一种对if......else......语句的简化形式

//如何用条件操作符来表达下列语句?
if (a > 5)
        b = 3;
else
        b = -3;

//  可以表示为   a>5?b=3:b=-3
逗号表达式 exp1, exp2, exp3, …expN 1.逗号表达式,就是用逗号隔开的多个表达式。 2.逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

if (a =b + 1, c=a / 2, d > 0)
//只有最后的d>0起判断作用

有时候可以利用逗号表达式来简化代码

a = get_val();
count_val(a);
while (a > 0)
 {
        //业务处理
        a = get_val();
        count_val(a);
}

//如果使用逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
 {
         //业务处理
 }

下标引用、函数调用和结构成员 [ ] 下标引用操作符

操作数:一个数组名 + 一个索引值

 ( ) 函数调用操作符

操作数:至少有1个操作数(函数名),参数也是其操作数

访问一个结构的成员

1、. 结构体 . 成员名 2、-> 结构体指针 -> 成员名

表达式求值        表达式求值的顺序一部分是由操作符的优先级和结合性决定。同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。 隐式类型转换         C 的整型算术运算总是至少以缺省(默认)整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型 提升 。(字符在内存中本质是128-127的整数,ASCII码值取值是0-127,是整型,因此字符型通常也被归类到整型家族)

下面以一个计算实例来详细看一下整型提升:

还有哪些例子可以说明整形提升的存在?

1、

2、 

 

算术转换         如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换 。

 

        如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。

 操作符的属性 复杂表达式的求值有三个影响的因素。 1. 操作符的优先级 2. 操作符的结合性 3. 是否控制求值顺序。 两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。 操作符优先级

 

*如果我们没有很好的理解操作符的属性,就可能写出一些问题表达式,导致程序出现bug,以下为例:

1、

 2、

  3、

int main()
{
	int i = 10;
	i = i-- - --i * (i = -3) * i++ + ++i;
	//i=i-- - --i *i*i++ + ++i,()内的值先算,此时所有的i=-3
	//但之后我们只能保证后置--和++先于前置--和++先于*先于+和减,但在同一优先级却不能决定顺序
	printf("i = %dn", i);//因此计算路径有很多
	return 0;
}

以下是该段代码在不同编译器上的运行结果,因此属于问题代码 

 4、

 5、

Linux环境下运行结果是;

10

4

vs2013环境下运行结果是: 

12

4

        这段代码中的第一个 + 在执行的时候,第三个 ++ 是否执行,这个是不确定的,因为依靠操作符的优先级和结合性是无法决定第一个 + 和第三个前置 ++ 的先后顺序。

总结:我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的,因此在写程序的时候要尽量避免写太过复杂的表达式。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1028215.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号