C语言基础3

内容提要

  • 回顾
  • 运算符(细节)
  • 流程控制

回顾

变量

概念:程序执行过程中可以改变的量就是变量。

  • 变量代表的是内存中的一块存储单元,用来存放数据。
  • 变量都有一个别名,一般称之为变量名,变量名的作用是引用变量。

语法:

// 声明变量的同时给变量赋值(变量的初始化)
// 如果不给变量赋初始值,系统会随机分配
int a = 10;

//先声明再赋值
int b;
b = 10;

//对变量的初始值进行覆盖式赋值
//基本数据类型(整型,浮点型,字符型):创建的变量,对应的内存中的存储区域是栈区。
// 栈区的特点:访问速度快 ,由系统自动申请自动释放,申请的内存单元的大小是固定值
int c = 10; // c:10
c = 20;     // c:20  

//同一类型的变量可以连续申请,使用逗号分隔
int a1,a2,a3;
a1 = 12;
a2 = 14;
a3 = 13;

int b1 = 12,b2 = 13,b3 = 14;

命令:
标识符:C语言中的标识符,包括变量名,函数名,数组名,结构体名,共用体名,枚举名等。

规则:

​ ①必须以字母(a~z, A~Z)或者下划线(-)开头,只能包含字母,数字,下划线

​ ②c编译系统对大小写敏感(区分大小写)

​ ③不能使用 c提供的关键字和预处理指令作为自定义标识符

分类:

​ ①小写字母+下划线命名:一般用于变量和函数,举例:_int,set_user,set()

​ ②大写字母+下划线命名:一般用于符号常量和枚举,举例:_INT,SET_USER

基本类型数据

分类:

​ 整型:short(2字节)int(4字节) long(32位系统:4字节 ,64位系统:8字节) longlong

​ 浮点型:float(4字节) double(8字节 ) long double(gcc编译器:16字节)

​ 字符型:char(1字节)

与内存的关系:

​ 基本类型数据都是运行在内存中,他们在内存中是以二进制的方式存储的。(整型是以二进制补码的形式存在,浮点型针对指数部分和尾数部分分开存储,字符型在内存中存放的是字符对应的ASCII码的二进制形式)

关于原码,反码,补码:

①原码:我们程序中正常的数值转换出来的二进制就是原码

②反码:反码的作用就是实现原码到补码的转换,转换规则:原码除符号位取反产生反码 ,反码+1产生补码。

③补码:我们程序中的数据在内存中是以二进制补码形式存储的

正数的原码,反码,补码一致;负数的原码,反码,补码不同

计算机底层没有减法运算 ,只有加法运算:比如:5-3,底层会进行转换:(5+(-3))

关于符号位:0代表正数,1代表负数

运算符

混合运算

①自动类型转换(隐式转换)

​ 转换规则:由低到高,直接转换

1>(低)int →unsigned →long →double(高)

2>(低)char或者short→int(高)

3>(低)float→ double(高)

举例:int a = 10,double b = a + 12.3

注意:同一个表达式中,不同数据类型是无法参与运算的,运算的时候需要转换为同一数据类型,才能参与运算,这里的类型提升只是临时性的提升,并不会改变其原本的数据类型。

②强制类型转换(显示转换)

语法:(type)表达式

举例:(double)a,(int)(x+y),(int)x+y,(flloat)(5/3)

注意:强制类型转换的时候,也只是临时提升,并不会改变其在内存中的 存储大小,同时强制类型转换有风险,可能会丢失精度。最常见的转换是,小数转整数,会丢失小数部分。举例:double a = 12.5;int b = (int )a;输出后a = 12.5,b = 12.

运算符

image-20250208173021495

表达式

表达式 = 运算数 + 运算符

image-20250208173055222

运算符

算术运算符

基本的算术运算符

+,-:正负值运算符(单目运算符:只有一个运算数 ),举例:+5,-5

+,-,*,/,%:加减乘除取余运算符(双目运算符:有两个运算数),注意:进行除法运算时,除数不能为0

这些算术运算符的运输算顺序与数学上的运算顺序是相同的。

表达式和运算符的优先级与结核性

算术表达式:是指用算数运算符和括号将运算对象连接起来,符合c语言规范的式子,例如

a * b /c - 1.5  +'a'
  • 表达式中各运算的运算顺序,必要时需要添加括号,例如:

    (a+b)/(c+d) != a+b/c+d
    
  • 表达式中各运算对象的数据类型,特别是整型相除,C语言规定,两个整数相除,其结果为整数。例如:

    7/6的值为1
    4/7的值为0
    面试题:(1/2) + (1/2) 的结果是多少?正确答案是0
    

    优先级与结核性:在表达式求解的时候,先按运算符的优先级级别的高低次序执行。若一个运算对象两侧的运算符的优先级相同,则按规定的结合方向处理

    各种运算符的结合方向:

    ①算术运算的结合方向:"自左向右"也就是运算对象先于左边的运算符结合,例如:

    a - b + c // 先执行a -b ,然后执行 +c运算
    

    ②有些运算符的结合方向:“自右向左”,也就是运算对象先与右边的运算符结合,例如:

    i++
    

    ③若一个运算符两侧的数据类型不同,会自动转换成同类型后进行计算。

自增++,自增–运算符

作用:使变量的值增1或者减1

结合方向:“自右向左”

++i,–i

表示在使用该运算符对象之前,先让运算符自身增1或者减1,然后再使用他,也就是使用增1或者减1后的值,先计算,后使用

例如:

int n = 1;   //n:1
int x = ++n; //x:2 ,n:2等价于n = n+1,x = n

i++,i–

表示在使用该运算符对象之后,才让运算符自身增1或者减1, 也就是先使用它的值,再让运算数自身增1或者减1,先使用,后计算

例如:

int n= 1;     //n:1
int x = n++;  //x:1 n:2等价于x= n,n = n+1

总结:不管是 ++i还是i++,运算数i自身都增1;同理不管是–i还是i–,运算数自身都减1,他们的不同之处在于(整体赋值)的先后顺序。

注意:

①增1与减1运算符只适用于整型变量或字符型变量,而不能 用于其它类型的变量

②增1与减1运算符不能用于常量或表达式,例如:--5,(i+j)++等都是违法的

课堂练习

要求:推导以下表达式的i和n的值

int i = 1;
int n = i++ + (++i) - (--i) + i--;

赋值运算符

“=”称之为赋值运算符,其作用是将一个数据赋值给一个变量。如:int a = 5;

执行赋值运算的结果,是将右边的数据存入左边变量对应的内存单元中,赋值运算顺序:自右向左

赋值规则

如果赋值运算符 两侧的类型不一致,则在赋值时进行 类型转换,转换规则为:

  • 实型 -> 整型变量 :舍弃小数部分。例如:int a = 5.5,a的结果是5
  • 整型->实型变量:数值不变,以浮点型存储。例如:double a = 5, a 的结果是5.000000
  • 字符型->整型变量:放在整形的低8位,保持原值不变规则,例如:int a =‘A’
image-20250208114507715

赋值表达式

主要实现赋值运算的表达式。

语法:

变量 = 表达式;

案例:

a = 5;
y = 2 * x +3;
a = a + 1;

作用:将右边表达式的值赋值给左边的变量。赋值表达式的取值取自左边变量的值。

复合赋值运算符

+=,-=,*=,/=,%=...(&=,|=,>>=,<<=,~=,^=)

左右两侧操作完毕后,赋值给左侧的变量,例如:

a += 3;等价于a = a + 3;
int c = 2;
c /= c; 等价于c = c/=c;

// ...其他复合赋值运算符类似

注意:

①在运算时,不能将 (=) 写作( ==)

②赋值运算符的优先级属于最低(除了逗号运算符以外)一般都是最后运算

关系运算符

表达式 = 运算数 + 运算符

定义:

>,<,>=,<=,==,!==

  • 所有的关系运算符都是二目运算符(二元运算符,双目运算符),运算符的左侧和右侧可以是变量,可以是常量,,还可以是表达式。举例:a > b,5 > 6,a+b>c
  • 关系运算符运算的结果是布尔类型,要么为真(非0,true-需要引入stdbool.h),要么为假(0,flase-需要引入stdbool.h)

说明:

1.标准c中没有布尔类型的,非0代表真,实际操作中使用数字1,0代表假

​ while(0)循环一次都不执行

​ while(1)死循环,无限循环

2.真在输出的结果为1,假在输出的结果为0

​ printf(“%d\n”,3<2);结果为0

​ printf(“%d\n”,3>2);结果为1

用作条件判断的时候,非0代表真,但是系统输出真的结果为1

注意:

​ ①算术运算符的优先级高于关系运算符,例如:2 + 3 > 1 + 1等价于(2+3)>(1+1)

​ ②关系运算符是二元(双目)运算符,不要连用,例如:

/*************************************************************************
	> File Name: demo01.c
	> Author: FPF
	> Description:
	> Created Time: 2025年02月08日 星期六 14时27分25秒
************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
	// 测试两个横等于
	int score = 80;
	printf("%d\n",0<score<=100);// 恒等于1
	printf("%d\n",100>=score>0);// 恒等于1
	printf("%d\n",60>=score>0); // 恒等于0
	printf("%d\n",0<score<=60); // 恒等于1
	
	return 0;
}

经过测试发现,不会报错,但是没有意义,程序中千万不能这么写!!!

正确得到写法:score> 0&&score <= 100

​ ③不能将==写成=,==:关系运算符,=:赋值运算符

​ ④一般浮点型进行比较,建议将两个数相减,结果和0进行比较,如果等于0,表示两个浮点数相等

​ 举例1:

​ float a = 22.2;

​ float b = 22.2;

​ a == b; 不推荐这种写法

​ a - b == 0; 推荐这种写法

​ 举例2:

​ float x = 2.0;

​ float y =11.1; //近似存储:11.099995

​ float z = x*y; //实际:22.199999,我们看到的是22.2

​ z == 22.2 //此时结果为假,所以这种写法不靠谱

两个浮点数的比较:两个浮点数相减跟0比 double a = 10; int b = 10; a == b;此时

a - b ==0; 结果为真,说明a等于b ,如果为假,a不等于b

a - b >0;结果为真,说明a大于b

a - b < 0;结果为真,说明a小于b

a - b == 0.000001:结果是真,人为的认为0.000001的误差能够接受,我们也认为a = b

逻辑运算符

运算结果要么为真(非0)要么为假(0)

!:非(逻辑非)单目(一元)运算符,并且只能在操作数的左侧;非真即为假,非假即为真。(取反)

  • 对一个数或者表达式去非奇数次,结果与原值相反,!(a%2!=0)取偶数次
  • 对一个数或者表达式去非偶数次,结果与原值相反,!(a%2==0)取奇数次

&&:与(逻辑与)双目(二元 )运算符,当左右两侧的数据都为真时,最终结果才为真(有假则为假)当逻辑与运算时,左侧为假,右侧结果不会影响最终的结果,因为右侧压根就不会执行,最终的结果就是左侧的结果,这种现象称之为短路效果(短路与),这是c语言中提供的一种惰性运算,就是减少运算次数。

案例:

5 > 6 && 6 > 5;    // 0

||:或(逻辑或)双目(二元)运算符,当左右两侧的数据都为假时,最终结果才会为假(有真则为真)当逻辑或运算时,==左侧为真,右侧结果不会影响最终的结果,右侧压根不再执行,最终结果就是左侧的结果,这种现象称之为短路效果(短路或),这是c语言中提供的一种惰性运算,就是减少运算次数。

案例:

5 > 6 || 6 > 5;    //1

逗号运算符

作用:将若干个表达式“产量起来”,如:3+5,6+8;

别称:顺序求值运算符

逗号表达式

语法:

表达式1,表达式2,...,表达式n

求解过程:按从左到右的顺序分别计算各个表达式的值,其中最后一个表达式n的值就是整个逗号表达式的值

位运算

说明:按位(bit)来进行操作的运算符

语法:~,&,|,^,<<,>>

~:按位取反

说明:单目运算符,数据的每一个比特位取反,也就是二进制数位上0变1,1变0

演示:

0000 1010

1111 0101

举例:

unsigned char ret = ~0x05;   // 0000 0101 ---> 1111 1010 
printf("%d\n",~5);  // -6 

&:按位与

说明:双目运算符, 对于运算符左右的两个数,对应二进制数据位都为1时,结果为1,否则为0

演示:

0000 1010

1010 1000


0000 1000

举例:

5 & 6 = 4;// 0000 0101 & 0000 0110 = 0000 0100 

|:按位或

说明:双目运算符,对于运算符左右的两个数,对应的二进制数据位有一个1,结果为1,否则为0

演示:

0000 1010

1010 1000


1010 1010

举例:

5|6=7; // 0000 0101 | 0000 0110 = 0000 0111

^:按位异或

说明:双目运算符,对于运算数左右的两个数,对应二进制数据位数据相同,结果为0,不同为1

演示:

0000 1010

1010 1000


1010 0010

举例:

5 ^ 6 = 3 //0000 0101 ^ 0000 0110 =  0000 0011

0000 0011 = 1 ∗ 2 1 1* 2^1 121 + 1 ∗ 2 0 1* 2^0 120 =3

<<:左移,按位往左偏移

说明:原操作数所有的二进制位数向左移动指定位

无符号左移:

  • 语法:

    操作数 << 移动位数
    
  • 举例:

    unsigned int a = 3 << 3; //计算规则:3 * 2 ^ 3
    unsigned int b = 5 << 4; //计算规则:5 * 2 ^ 4
    

原数据3:00000000 00000000 00000000 00000011

左移3位:00000000 00000000 00000000 00011000

有符号左移

  • 语法:

    操作数 << 移动位数
    
  • 举例:

    int a = 3 << 3;  //-24 计算规则:-3 * 2 ^ 3  
    char b = 240 << 2; //960  计算规则: 240 * 2 ^ 2,很明显,此时计算结果有误。
    
  • 注意;

    • 如果移出的高位都是0,我们可以这样理解:a << n,可以看作是:$ a * 2^n$
    • 如果移出的高位都是1,我们是不能使用上面的计算公式的。
    >>:右移,按位往右偏移

    说明:源操作数的所有的二进制操作数向右移动指定位,移出的数据舍弃。

    如果操作数是无符号数:左边用0补齐

    如果操作数是有符号数:左边用什么补全,取决于计算机系统;

    • 逻辑右移:用0补全
    • 算术右移:用1不全

    大部分情况下,系统遵循“算术右移”

    无符号右移:

    语法:

    操作数 >> 移动位数
    

    举例:

    unsigned char a = 3 >> 3 ; // 0
    

    有符号右移:

    语法:

    操作数 >> 移动位数
    

    举例:

    char a = -3 >> 3; // -1
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值