达内C语言学习(day04)

每日英语:

operation:操作

core dumped:核心已转储,表示程序崩溃了

inc = increase:自增

dec = decrease:自减

rel = relationship:关系

logic:逻辑

shift:移位

回顾:

1. 变量的数据类型

1.1 数据类型的基本功能

​ 指定变量分配的内存大小

1.2 12类基本数据类型

​ char/unsigned char/short/unsigned short/int/unsigned int/long/unsigned long/long long/unsigned long long/float/double

​ 注意:unsigned int 和unsigned long随着操作系统的为数不一样而不一样

1.3 详解字符类型

​ 字符常量:‘A’

​ 字符变量:存储的不是字符,而是存储对应的ASCII码(实际就是1个字节的整数)

​ 占位符:%c

1.4 整数类型:int

​ short/unsigned short/long/unsigned long进行修饰

​ 六种形式

​ unsigned long a = 250; 等价于 unsigned long int 啊= 250;

1.5 整型常量

​ 100/100L/100UL/100u等

1.6 浮点数

​ float和double

1.7 数据类型和对应的占位符

​ %c / %hhd / %hd / %hu / %d / %u / %ld / %lu / %f /%lf / %g / %lg

​ 注意:回滚现象

2. 进制转换

2.1 计算机只认二进制

​ 内存只能存储二进制

2.2 8进制, 10进制, 16进制

​ 这三种进制仅仅是二级制的另外一种表现形式而已

​ 内存中的数不会随着进制的改变而改变

2.3 2进制,8进制,10进制之间转换

​ 用计算器

​ 2进制和16机制的口算必须口算!

​ 例如:

​ 0x83ac9fe2(4字节数据):1000 0011 1010 1100 1001 1111 1110 0010

2.4 大招

​ 务必拿下数据在内存中的二进制存储形式


第五课:运算符和表达式

1. 概念

​ 明确计算机程序最终玩的是内存,而内存存储的是各种二进制数据

​ 这些数据之间必然存在各种运算,浙江就需要相应的数据运算的操作方式

​ 运算符:对内存中的数字进行各种运算的符号,例如:+,-,*,/等

​ 表达式:运算符和数字结合起来的式子,简称表达式

2. C语言提供的运算符

2.1 算数运算符

​ 加, 减, 乘, 除, 取余(求模),对应的符号:+, -, *, /, %

注意:

​ 1. 如果参与除法计算的两个数字是整型数则计算结果之保留整数部分

​ 例如:5 / 2 = 2

​ 2. / 和 % 不能对0进行操作,否则程序崩溃

​ 例如:5 / 0 或者 5 % 0

​ 3. % 不能对浮点数使用,否则程序崩溃

​ 4. % 结果与其左边的数字符号一致

​ 例如:-7 % 2 = -1 7 % -2 = 1

​ 5. / 如果除数位浮点数,最后得到int无穷大的结果

​ 例如:5 % 0.0

案例演练运算符:

​ 实验步骤:

mkdir 桌面/tarena/stdc/day04
cd 桌面/tarena/stdc/day04
vim oper.c
gcc -o oper oper.c   // 建议练习分步法
./oper
  1 /*算数运算符演练*/
  2 #include <stdio.h>
  3 
  4 int main(void)
  5 {
  6         int a = 5, b = 2, c = 0;
  7 
  8         printf("a + b = %d\n", a + b);
  9         printf("a - b = %d\n", a - b);
 10         printf("a * b = %d\n", a * b);
 11         printf("a / b = %d\n", a / b);
 12         printf("a %% b = %d\n", a % b);
 13 
 14         //printf("a / c = %d\n", a / c);
 15 
 16         double d = 0;
 17         //printf("a %% d = %lf\n", a % d);//程序崩溃
 18         printf("a / d = %lf\n", a / d);
 19 
 20         printf("-7 / 2 = %d, 7 / -2 = %d\n", -7 / 2, 7 / -2);
 21         printf("-7 %% 2 = %d, 7 %% -2 = %d\n", -7 % 2, 7 % -2);
 22 
 23         return 0;
 24 }

​ 结果:

a + b = 7
a - b = 3
a * b = 10
a / b = 2
a % b = 1
a / d = inf
-7 / 2 = -3, 7 / -2 = -3
-7 % 2 = -1, 7 % -2 = 1

2.2 赋值运算符

​ =, 就是将右边的值给左边的变量,也就是将变量对应的内存值进行修改

​ 形式1:

​ int a = 10;

​ a = 20;

​ 形式2:

​ int a, b, c;

​ a = b = c = 10;

​ printf("%d %d %d\n", a, b , c);

​ 形式3:

​ 符复合运算符:赋值运算符=和其他运算符结合起来使用

​ 例如:

​ a += b; 等价于a = a + b;

​ a -= b; 等价于a = a - b;

​ a *= b; 等价于a = a * b;

​ a /= b; 等价于a = a / b;

​ a % = b; 等价于a = a % b;

​ 注意事项:不能个常量和表达式赋值:

​ 100 = 200; // gcc报错

​ 100 = a; // gcc报错

​ a + b = c; // gcc报错,gcc先算a + b结果肯定是一个常量(数字)

参考代码:assign.c
  1 /*赋值运算符演练*/
  2 #include <stdio.h>
  3 
  4 int main(void)
  5 {
  6         int a = 10;
  7         a = 250;
  8         printf("a = %d\n", a);
  9 
 10         int b, c, d;
 11         b = c = d = 250;
 12         printf("%d %d %d\n", b, c, d);
 13 
 14         b = 1;
 15         c = 2;
 16         b += c;// b = b + c 
 17         printf("b = %d, c = %d\n", b, c);
 18 
 19 
 20         return 0;
 21 }

结果:

a = 250
250 250 250
b = 3, c = 2

2.3 自增运算符(++)和自减运算符(–)

2.3.1 定义

​ 自增运算符就是让变量对应的内存数值加1

​ 自减运算符就是让变量对应的内存数值减1

2.3.2 四种形式

​ 前++:先对变量的值加1,后计算表达式的值

​ 例如:

​ int a = 1;

​ int b = 0;

​ b = ++a;

​ printf(“a = %d, b = %d\n”, a, b); // a = 2 b = 2

​ 后++:先计算表达式的值(b = a =1),后对变量的值加1(a++ = 1 + 1)

​ 例如:

​ int a = 1;

​ int b = 0;

​ b = a++;

​ printf(“a = %d, b = %d\n”, a, b); // a = 2 b = 1

​ 前–:先对变量值减1,后计算表达式的值

​ 例如:

​ int a = 2;

​ int b = 0;

​ b = --a;

​ printf(“a = %d, b = %d\n”, a, b); // a = 1 b = 1

​ 后–:先计算表达式的值,后对变量值减1

​ 例如:

​ int a = 2;

​ int b = 0;

​ b = a–;

​ printf(“a = %d, b = %d\n”, a , b); // a = 1 b = 2

2.2.3 不能对常量自增或者自减

​ 100++;报错

​ 100–;报错

参考代码:inc_dec.c
  1 /*自增自减运算演示*/
  2 #include <stdio.h>
  3 
  4 int main(void)
  5 {
  6         int a =1;
  7         int b = 0;
  8 
  9         //100++;  gcc报错
 10 
 11         b = ++a;
 12         printf("a = %d, b = %d\n", a, b);   // a = 2, b = 2
 13 
 14         b = a++;
 15         printf("a = %d, b = %d\n", a, b);   // a = 3, b = 2
 16 
 17         b = --a;
 18         printf("a = %d, b = %d\n", a, b);   // a = 2, b = 2
 19 
 20         b = a--;
 21         printf("a = %d, b = %d\n", a, b);   // a = 1, b = 2
 22 
 23         return 0;
 24 }  
2.3.4 关系运算符

​ ==:等于

​ !=:不等于

​ >:大于

​ <:小于

​ >=:大于等于

​ <=:小于等于

​ 注意:

​ 1. 关系运算符的结果是:1(俗称真)或者0(俗称假)

​ 2. 不要进行连续的关系运算,例如:5<4<3,gcc编译器先算5<4,拿着结果0再跟3做比较

​ 问:如果要进行连续的关系运算,怎么办呢?

​ 答:采用逻辑运算实现

参考代码:rel.c
  1 /*关系运算符演示*/
  2 #include <stdio.h>
  3 
  4 int main(void)
  5 {
  6         printf("1 = 1的结果是%d\n", 1 == 1);
  7         printf("1 != 1的结果是%d\n", 1 != 1);
  8         printf("1 > 2的结果是%d\n", 1 > 2);
  9         printf("1 < 2的结果是%d\n", 1 < 2);
 10 
 11         // 注意:gcc编译器先算5>4的结果是0,然后拿着0和3比较,结果为1   
 12         printf("5>4>3的结果是%d\n", 5<4<3);
 13         printf("3<7<5的结果是%d\n", 3<7<5);
 14 
 15         return 0;
 16 }

结果:

1 = 1的结果是1
1 != 1的结果是0
1 > 2的结果是0
1 < 2的结果是1
5>4>3的结果是1
3<7<5的结果是1
2.3.5 逻辑(真真假假,假假真真)运算符
	1. 明确:计算机中的“真”就是非0(包括1),“假”就是0
	2. 逻辑运算符的类型:三类
   	1. 逻辑与:&&(并且,与此同时的意味)
    	2. 逻辑或运算:||(具有或者的意味)
    	3. 逻辑非:!(对着干)
  1. 逻辑与&&运算符的特点:

    ​ 使用语法:c = 表达式A && 表达式B;

    ​ 语义:只有当A和B的值都为真(非0),c的值才为真

    ​ 只要A,B有一个为假,c的值就为假

    ​ 例如:登录抖音时,只有用户名和密码都对了,都为真才能登录

    ​ 只要有一个不对,登录就是失败

    ​ 例如:1&& 1; // 结果为真

    ​ 1 && 0; // 结果为假

    ​ 0 && 250; //结果为假

    ​ 0 && 0; // 结果为假

  2. 逻辑或||运算符的特点:

    ​ 使用语法:c = 表达式A || 表达式B

    ​ 语义:只要A和B中有一个为真,c的值就为真

    ​ 只有A和B都为假,c的值就为假

    ​ 例如:登录抖音时,可以采用QQ登陆或者微信登陆或者手机号登陆

    ​ 只要有一个对了,就可以登陆抖音

    ​ 都不对,登陆失败

    ​ 例如:250 || 520; //真

    ​ 250 || 0; //真

    ​ 0 || 250; // 真

    ​ 0 || 0; // 假

  3. 逻辑非!运算符特点

    ​ 使用语法:!表达式A

    ​ 语义:A假结果为真,A真结果为假

    ​ 例如: !250; // 结果为假

    ​ !0; // 结果为真

2.3.6 切记:短路运算

​ 笔试题必考,开发常用

​ 形式1:A && B:如果A的值为假,B的1代码就不会被执行

​ 例如:

int a = 1;
1 > 2 && ++a;
printf("a = %d\n", a);	// a = 1


int b = 1;
2 > 1 && ++b
printf("a = %d\n", a);	// b = 2

​ 形式2:A || B:如果A的值为真,B的代码就不会被执行;如果A为假,B的代码接着被执行

int a = 1;
1 > 2 && ++a;
printf("a = %d\n", a);	// a = 2


int b = 1;
2 > 1 && ++b
printf("a = %d\n", a);	// b = 1
参考代码:logic.c
  1 /*逻辑运算符*/
  2 
  3 #include <stdio.h>
  4 
  5 int main(void){
  6 
  7         //逻辑非        
  8         printf("!1的结果是%d\n", !1);   // 0
  9         printf("!250的结果是%d\n", !250);       //0
 10         printf("!0的结果是%d\n", !0);   // 1    
 11 
 12         // 逻辑与
 13         printf("2 && 3的结果是%d\n", 2 && 3);   // 1    
 14         printf("0 && 3的结果是%d\n", 0 && 3);   // 0
 15 
 16         //逻辑或
 17         printf("2 || 3的结果是%d\n", 2 || 3);
 18         printf("0 || 1的结果是%d\n", 0 || 1);
 19         printf("1 || 1的结果是%d\n", 1 || 1);
 20 
 21         // 关系运算符bug:5<4<3,采用逻辑运算符解决
 22         printf("5<4<3的结果是%d\n", 5<4 && 4<3);        // o
 23 
 24         return 0;
 25 }

结果:

!1的结果是0
!250的结果是0
!0的结果是1
2 && 3的结果是1
0 && 3的结果是0
2 || 3的结果是1
0 || 1的结果是1
1 || 1的结果是1
5<4<3的结果是0
a = 1, b = 2
a = 2, b = 2
2.3.7 位(bit)运算
1.功能

​ 就是专门对内存中的二进制数进行各种运算

2.位运算四种形式

​ 位与:&

​ 位或:|

​ 位异或:^

​ 位反:~

3.位与&运算的特点

​ 语法:C = A & B;

​ 例如:

​ A:0 1 0 1 1 0 1 0 0x5a

​ B:1 1 1 0 0 0 1 1 0xe3

&----------------------------------

​ C:0 1 0 0 0 0 1 0 0x42

​ 规律:任何数跟0做位与,结果都是0,任何数1跟位与,保持原值

4.位或|运算符特点:

​ 语法:C = A | B

​ 例如

​ A:0 1 0 1 1 0 1 0 0x5a

​ B:1 1 1 0 0 0 1 1 0xe3

​ |----------------------------------

​ C:1 1 1 1 1 0 1 1 0xfb

​ 规律:任何数跟1做位或,结果都是1,任何数跟0位与,保持原值

5. 位异运算符特点:

​ 语法:C = A ^ B;

​ 例如:

​ A:0 1 0 1 1 0 1 0 0x5a

​ B:1 1 1 0 0 0 1 1 0xe3

​ ^----------------------------------

​ C:1 0 1 1 1 0 0 1 0xb9

​ 规律:相同为0,不同为1

6. 位反运算符对的特点

​ 语法:C = A ^ B

​ 例如:

​ A:0 1 0 1 1 0 1 0 0x5a

​ ~A:1 0 1 0 0 1 0 1 0xa5

​ 规律:1变0, 0变1

参考代码:bit.c
/*位运算符演示*/
#include <stdio.h>

int main(void){
	
	// 位与运算&
	printf("0x5a & 0xe3的结果是%#x\n", 0x5a & 0xe3);   // 01011010 & 11100011 = 01000010 = 0x42 
	printf("0x44 & 0xc1的结果是%#x\n", 0x44 & 0xc1);   // 01000100 & 11000001 = 01000000 = 0x40
	printf("0xa3 & 0xfe的结果是%#x\n", 0xa3 & 0xfe);   // 10100011 & 11111110 = 10100010 = 0xa2

	// 位或运算|
	
	printf("0x5a | 0xe3的结果是%#x\n", 0x5a | 0xe3);   // 01011010 | 11100011 = 11111011 = 0xfb
	printf("0x44 | 0xc1的结果是%#x\n", 0x44 | 0xc1);   // 01000100 | 11000001 = 11000101 = 0xc5
	printf("0xa3 | 0xfe的结果是%#x\n", 0xa3 | 0xfe);   // 10100011 | 11111110 = 11111111 = 0xff


	// 位异或运算^
	
	printf("0x5a ^ 0xe3的结果是%#x\n", 0x5a ^ 0xe3);   // 01011010 ^ 11100011 = 10111001 = 0xb9
	printf("0x44 ^ 0xc1的结果是%#x\n", 0x44 ^ 0xc1);   // 01000100 ^ 11000001 = 10000101 = 0x85
	printf("0xa3 ^ 0xfe的结果是%#x\n", 0xa3 ^ 0xfe);   // 10100011 ^ 11111110 = 01011101 = 0x5c


	// 位反运算~
	// 1. 0x5a默认的数据类型为什么类型int类型,4字节,32位
	// 2. 0x5a真正的二进制是:0000 0000 0000 0000 0000 0000 0101 1010
	// 3. ~0x5a结果:	  1111 1111 1111 1111 1111 1111 1010 0101
	// 16进制结果:		  f	f     f   f    f    f    a     5
	printf("~0x5a结果是%#x\n", ~0x5a);
	printf("~0x5a结果是%d\n", ~0x5a);
	printf("~0x5a结果是%u\n", ~0x5a);
	
	// 问:就想看到0x5a,不想看到前面一堆的f、
	unsigned char a = ~0x5a; // 将4字节的0xffffffa5的1字节0xa5保存到a变量中,其他的f全部丢失
	printf("a = %#x\n", a);
	
	char b = ~0x5a; // 将4字节的0xffffffa5的1字节0xa5保存到a变量中,其他的f全部丢失
	printf("b = %#x\n", b);
	
	
	return 0;
}	

结果:

0x5a & 0xe3的结果是0x42
0x44 & 0xc1的结果是0x40
0xa3 & 0xfe的结果是0xa2
0x5a | 0xe3的结果是0xfb
0x44 | 0xc1的结果是0xc5
0xa3 | 0xfe的结果是0xff
0x5a ^ 0xe3的结果是0xb9
0x44 ^ 0xc1的结果是0x85
0xa3 ^ 0xfe的结果是0x5d
~0x5a结果是0xffffffa5
~0x5a结果是-91
~0x5a结果是4294967205
a = 0xa5
b = 0xffffffa5
2.3.8. 移位运算符:<<,>>
  1. 功能:就是将二进制数统一向左或者向右移动n个位置(简称左移,右移)

  2. 左移,右移:

    左移:A << B

    语义:将A左移B个位置

    右移:A >> B

    语义:将A右移B个位置

    例如:

    ​ 1 << 3:将1左移3位(bit)

    ​ 3 >> 1:将3右移1位(bit)

    1. 移位运算符的特点:

    1.向左移动后右边空出来的数据用0来填充

    ​ 例如:A数据前提是char类型

    ​ A = 0x5a = 01011010

    ​ A << 2 = 01011010 << 2 结果为:011010 + 00 即:01101000 = 0x68

    2.无符号类型数字右移时,左边空出来的数据用0填充

    ​ 例如:01011010 >> 2 结果为:00 + 010110 即:00010110 = 0x16

    3.有符号类型数字右移时,左边空出来的数据用符号位来填充

    ​ 例如:10100101(前提是char类型)>> 2 结果为:11 + 101001 即:11101001 = 0xe9

    4.左移n位相当于乘以2的n次方

    5.右移n位相当于除于2的n次方

    切记:如果将来程序中涉及乘以或者除以2的n次方运算,务必用左移或者右移

    ​ 严重鄙视用*或者/,因为乘或者效率极低

    ​ 例如:

    int a = 1;
    int b = a * 4;    //  遭鄙视的垃圾代码
    int b = a << 2;   // 高薪代码
    

    6.移位运算不会改变变量本身的值

    ​ 例如:

    int a = 3;
    int b = a << 1;
    printf("a = %d, b = %d\n", a, b);	// a = 3 ,b = 6
    
2.3.9 实际开发常用的位操作公式(切记!):
位清零:通过一下需求找规律:

​ 1. 将某个数据A第0位清0,其他位保持不变:

​ A &= ~(1 << 0); // 等价于:A = A & ~(1 << 0);

​ 2. 将某个数据A的第1位清0,其他位保持不变

​ A & = ~(1 << 1);

​ 3. 将某个数据A的第2位清零,其他位保持不变

​ A &= ~(1 << 2);

​ 4. 将某个数据的第0位清零和第1位清零,其他位保持不变

​ A &= ~(3 << 0); // 3的二进制0011

​ 5. 将某个数据的第1位清零和第2位清零,其他位保持不变

​ A &= ~(3 << 1);

​ 6. 将某个数据的第2位清零和第3位清零,其他位保持不变

​ A &= ~(3 << 2);

​ 7. 将某个数据的第0位清零和第1位清零和第2位清零,其他位保持不变

​ A &= ~(7 << 0); // 7的二进制是0111

​ 8. 将某个数据的第1位清零和第2位清零和第3位清零,其他位保持不变

​ A &= ~(7 << 1); // 7的二进制是0111

​ 9. 将某个数据的第0位清零,第1位清零,第2位清零和第3位清零,其他位保持不变

​ A &= ~(0xf << 0); // f的二进制是1111

​ 9. 将某个数据的第1位清零,第2位清零,第3位清零和第4位清零,其他位保持不变

​ A &= ~(0xf << 1); // f的二进制是1111

……

结论:连续位清零0,其他位保持不变

公式:A &= ~(B << C);

A:操作数据

B:连续的位数:1 / 3 / 7 / 0xF / 0x1F / 0x3F / 0x7F / 0xFF / 0x1FF / 0x3FF / …

C:起始位

​ 公式推导演练:目标:将0xA5(10100101)的第0位清0,其他位保持不变(结果:10100100 = 0xa4)

​ 最终代码:int a = 0xA5;

​ a & = ~(1 << 0); // 等价于a = a & ~(1 << 0);

​ 推导如下:

​ 1.先算:1 << 0 0000 0000 0000 0000 0000 0000 0000 0001

​ 2.然后算~(1 << 0) 1111 1111 1111 1111 1111 1111 1111 1110

​ 3.a的二进制 0000 0000 0000 0000 0000 0000 1010 0101

​ 4.然后算a & ~ (1 << 0); 0000 0000 0000 0000 0000 0000 1010 0101

​ 0 0 0 0 0 0 A 4

​ 5.然后把运算结果在赋值给a = 0x000000A4 = 0xA4

​ 公式推导演练:目标:将0xAF(10101111)的第1,2,3位清0,其他位保持不变(结果:10100001 = 0xA1)

​ 最终代码:int a = 0xAF;

​ a &= ~(7 << 1);

​ 推导:

​ 1.先算 7(0111) << 1 0000 0000 0000 0000 0000 0000 0000 1110

​ 2.然后再算~(7 << 1); 1111 1111 1111 1111 1111 1111 1111 0001

​ 3.a的二进制; 0000 0000 0000 0000 0000 0000 1010 1111

​ 4.然后算a & ~(7 << 1); 0000 0000 0000 0000 0000 0000 1010 0001

​ 5.最后将结果赋值给a = 0x000000A1 = 0xA1

位置1操作,通过一下需求找规律:

​ 1.将某个数据A的第0位置1,其他位置保持不变

​ A |= (1 << 0);

​ 2.将某个数据A的第1位置1,其他位置保持不变

​ A |= (1 << 1);

​ 3.将某个数据A的第2位置1,其他位保持不变

​ A |= (1 << 2);

​ 4.将某个数据的A的第0,1位置1,其他位保持不变

​ A |= (3 << 0);

​ 4.将某个数据的A的第1,2位置1,其他位保持不变

​ A |= (3 << 1);

结论:连续位置1,其他位保持不变

公式:A |= ~(B << C);

A:操作数据

B:连续的位数:1 / 3 / 7 / 0xF / 0x1F / 0x3F / 0x7F / 0xFF / 0x1FF / 0x3FF / …

C:起始位

​ 公式推导演练:目标:将0xA1(10100001)的第1,2,3位置1,其他位保持不变(结果:10101111 = 0xAF)

​ 最终代码:int a = 0xA1;

​ a |= (7 << 1);

​ 推导如下:

​ 1.先算:7 << 1: 0000 0000 0000 0000 0000 0000 0000 1110

​ 2.a的二进制: 0000 0000 0000 0000 0000 0000 1010 0001

​ 3.a | (7 << 1) 0000 0000 0000 0000 0000 0000 1010 1111

​ 4.最后将结果赋值给a=0x000000AF = 0XAF

参考代码:bit2.c
  1 /*位运算终级公式演练*/
  2 #include <stdio.h>
  3 
  4 int main(void)
  5 {
  6         int a = 0x5a; //01011010
  7 
  8         // 将a变量的第四位清零,其他位保持不变
  9         a &= ~(1 << 4); // 01001010
 10         printf("a = %#x\n", a); // 0x4a
 11 
 12 
 13         // 将a变量的第2,3位清领,其他位保持不变
 14         a &= ~(3 << 2);
 15         printf("a = %#x\n", a); // 0x42
 16 
 17         //将a变量的第4位置1(0001 0000)
 18         a |= (1 << 4);  // 0x42:0100 0010     
 19         printf("a = %#x\n", a); // 0101 0010 0x52
 20 
 21         // 将第2,3位置1
 22         a |= (3 << 2); // 0000 1100
 23         printf("a = %#x\n", a); // 0101 1110  0x5e
 24 
 25 
 26         int b = 0x12345678;
 27         // 将b的第4,5,6,7,8连续五位清0    
 28         b &= ~(0x1f << 4);
 29         printf("b = %#x\n", b);
 30         return 0;
 31 }

建议:如果建拿过来操作的为数大于22位,建议先统一清0后置1

例如:将数据0xe578a431的第4,5,6,7置0xa,其他位保持不变,代码:

int a = 0xe578a431;
a &= ~(0xf << 4);	// 先将4,5,6,7位清0
a |= (0xa << 4);   // 然后将4,5,6,7位的值修改为0xa
参考代码:bit3.c
  1 /*位运算终极公式演练*/
  2 //结论:将来位操作,如果操作的位数大于等于2位,建议先统一清0后置1
  3 #include <stdio.h>
  4 
  5 int main(void)
  6 {
  7         int a = 0xfa78dc23;
  8 
  9         //将a数据中的0xc修改为0x8,因为c是4位二进制,所以用0xf
 10         a &= ~(0xf << 8);
 11         a |= (0x8 << 8);
 12         printf("a = %#x\n", a);
 13 
 14         //将a数据中的0xa7修改位0x7a
 15         a &= ~(0xff << 20);
 16         a |= (0x7a << 20);
 17 
 18         printf("a = %#x\n", a); // 0xf7a8d823
 19 
 20 
 21         //将a中的0x8d8修改为0xccc
 22         a &= ~(0xfff << 8);
 23         a |= (0xccc << 8);
 24         printf("a = %#x\n", a);
 25 
 26         return 0;
 27 }

结论:

a = 0xfa78d823
a = 0xf7a8d823
a = 0xf7accc23
2.3.10 取地址运算符&和解引用*运算符:

1.明确内存地址特性:计算机内存地址由32位二进制数组成,也就是任何地址都是32位,4字节

2.取地址运算符&作用:获取一个变量对应的内存首地址,打印地址值的占位符%p

3.取地址运算符&语法格式:&变量名;

​ 例如: int a = 250; // 分配4字节空间放250这个数字

​ pritnf(“变量a的首地址是%p\n”, &a);

4.解引用运算符*作用:根据变量的首地址获取内存中的数据

​ 或者根据变量的首地址来修改内存中的数据

5.解引用运算符*的语法: *变量的首地址;结果就是可以操作内存了

​ 例如:

int a = 250;
printf("变量a的首地址是%p\n", &a);
printf("a = %d\n", *&a);	// 根据变量a的首地址获取内存中的数据250
*&a = 520;		// 根据变量a的首地址修改对应的内存数据,将250修改为520

​ 切记:只要获取了变量的首地址,就可以对这个变量的内存无所欲为,可读取里面的数据

​ 还可以修改里面的数据

参考代码:address.c
*取地址运算符&和解引用*演练*/
#include <stdio.h>

int main(void)
{
       int a = 250;
       printf("变量a的首地址是%p\n", &a);      
       return 0;
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值