四、赋值操作符
0x00 概览
📚 用法:用来重新赋值一个变量的值;
0x01 一般赋值
📚 赋值方法:
💬 赋值操作符是个很棒的操作符,它可以让你得到一个你之前不满意的值:
int main() { int weight = 120; // 体重120,不满意,我要变瘦点! weight = 89; // 不满意就赋值~ double salary = 10000.0; // 我:老板!我要加薪! salary = 20000.0; // 老板:好的,没有问题! return 0; }
0x02 连续赋值
📚 定义:连续赋值(continuous assignment),即一次性赋多个值;
📜 建议:建议不要使用连续赋值,会让代码可读性变差,而且还不容易调试;
💬 代码演示:连续赋值的使用方法;
int main() { int a = 10; int x = 0; int y = 20; a = x = y+1;// 👈 连续赋值 x = y+1; a = x; // 👆 这样写更加清晰爽朗而且易于调试 return 0; }
0x03 复合赋值符
📚 意义:复合赋值运算符是为了减少代码输入量而设计的;
📌 注意事项:
① x = x + 10 与 x += 10 的意义等价;
② 可以提高代码的整洁度,让代码更加整洁;
💬 代码演示:复合赋值符的使用方法
int main() { int x = 10; x = x + 10; x += 10; //复合赋值符的写法 (和上面是等价的) return 0; }
五、单目操作符
0x00 概览
❓ 什么是单目操作符?
💡 在运算中只有一个操作数的操作符,叫做单目操作符;
0x01 逻辑反操作 !
📚 作用:可以让真变为假,也可以让假变为真;
💬 逻辑反操作的用法:
int main() { int a = 10; printf("%d\n", !a); // 将真变为假, 0 int b = 0; printf("%d\n", !b); // 将假变为真, 1 return 0; }
🚩 运行结果: 0 1
💬 最常用的用法:
int main() { int flag = 5; if ( flag ) // flag != 0 -> hehe printf("hehe\n"); // flag为真,打印hehe if ( !flag ) // flag == 0 -> haha printf("haha\n"); // flag为假,打印haha return 0; }
🚩 运行结果: hehe
0x02 负值 -
📚 作用:把一个数置为负数;
💬 负值的用法:
int main() { int a = 10; a = -a; // 在a前面放一个负号 printf("%d", a); return 0; }
🚩 运行结果: -10
0x03 正值 +
📚 作用:一般都省略掉了,和数学里面一样;
💬 加号一般都不写的:
int main() { int a = +5; // 一般都省略掉了,和数学里一样 printf("%d", a); return 0; }
🚩 运行结果: 5
0x04 取地址操作符 & 与 解引用操作符 *
📚 理解:
① 取地址操作符可以理解为取快递;
② 解引用操作符可以理解为拆快递;
(指针章节会详解)
💬 用法演示:
int main() { int a = 10; int* pa = &a; // 取地址操作符 ( 随后将地址存放在int* pa里 ) *pa = 20; // 解引用操作符 通过p里存的值找到它所指向的对象; // *p就是a, 将*p赋值为20,a就会变为20; return 0; }
🔑 解析:
① 首先 int* pa 是一个指针变量(如果不知道什么是指针,可以暂且理解为是一个快递包裹);
② 快递包裹里装的是内存地址,我们使用 取地址操作符& 取出 a 的地址,存放到这个包裹里(int* pa = &a);
③ 这时,我们想修改 a 的值,我们要打开包裹进行修改,可以通过 解引用操作符* 将 a 修改为新的值(*pa = 20);
0x05 操作数的类型长度 sizeof( )
📚 作用:计算变量所占内存空间的大小,单位是字节;
📌 注意事项:
① sizeof 括号中的表达式不参与运算;
② sizeof 本质上不是函数,所以可以省略括号,但是 sizeof 后面是类型时不可以省略括号;
💬 sizeof 的用法:
int main() { int a = 10; char c = 'a'; char* pc = &c; int arr[10] = {0}; /* sizeof 计算的变量所占内存空间的大小,单位是字节 */ printf("%d\n", sizeof(a)); //4; printf("%d\n", sizeof(int)); //4; printf("%d\n", sizeof(c)); //1; printf("%d\n", sizeof(char)); //1; printf("%d\n", sizeof(pc)); //4; 32位系统中 printf("%d\n", sizeof(char*)); //4; printf("%d\n", sizeof(arr)); //40; 4x10=40 printf("%d\n", sizeof( int [10] )); //40; return 0; }
💬 下列代码的运行结果为什么?
int main() { short s = 0; int a = 10; printf("%d\n", sizeof(s = a + 5)); printf("%d\n", s); }
🚩 运行结果: 2 0
❓ 为什么是 s 还是 0 呢? s = a + 5,s 不应该是 15吗……
🔑 解析:15个🔨15,sizeof 括号中的表达式不参与运算!
💬 下列代码输出后 (1) (2) (3) (4) 分别是多少(32位)?
void test1(int arr[]) //传参传过来的是首元素 { printf("%d\n", sizeof(arr)); // (3) } void test2(char ch[]) { printf("%d\n", sizeof(ch)); // (4) } int main() { int arr[10] = {0}; char ch[10] = {0}; printf("%d\n", sizeof(arr)); // (1) printf("%d\n", sizeof(ch)); // (2) test1(arr); test2(ch); return 0; }
💡 答案:(1)40 (2)10 (3)4 (4)4
🔑 解析:
① (1) 一个int型大小为4,数组大小为10,4x10 = 40,所以答案为40;
② (3) 一个char型大小为1,数组大小为10,1x10 = 10,所以答案为10;
③ (3) (4) 数组名传参,传过去的虽然是是首元素地址,因为首元素的地址也是地址
所以要拿一个指针来接收它。本质上,arr 和 ch 为指针,而指针的大小,
是4个字节或者8个字节(具体是几个字节看操作系统),题目中为32位,所以答案为4;
❌ 错误示范:
int main() { /* sizeof 后面是类型时不可以省略括号 */ int a = 10; printf("%d\n", sizeof a ); // 可以省略 ✅ printf("%d\n", sizeof int); // error! 不可以省略 ❌ return 0; }
🚩 运行结果: error: expected expression before 'int' printf("%d\n", sizeof int);
0x06 按位取反 ~
📚 作用:对一个数按位取反,0 变 1, 1 变 0;
📌 注意事项:
① 按位取反,1~0互换,包括符号位;
② 按位取反后,是补码;
💬 巧用按位取反:将某一个数的二进制位从右到左数的第三个数改为1;
int main() { int a = 11; a = a | (1<<2); // 00000000000000000000000000001011 11 // | 00000000000000000000000000000100 让他和“这个数字”按位或 //------------------------------------- // 00000000000000000000000000001111 此时这一位变成了1 // 如何创造出“这个数字”呢? // 1<<2; // 00000000000000000000000000000001 1 // 00000000000000000000000000000100 把他向左移动两位时1就到这了 // a|(1<<2) // 00000000000000000000000000001011 // | 00000000000000000000000000000100 //------------------------------------- // 00000000000000000000000000001111 printf("%d\n", a); //15 a = a & ( ~ (1<<2) ); // 如何再改回去? ↓ 让这一位改成0 // 00000000000000000000000000001111 让他和0按位与 // | 11111111111111111111111111111011 给他按位与一个“这样的数字” //------------------------------------- // 00000000000000000000000000001011 把这一位又还原成0了 // 1<<2,同上 // 00000000000000000000000000000100 这个数字按位取反可以得到 ...1011 // ~ // 11111111111111111111111111111011 // a& ~ // 00000000000000000000000000001111 15 // & 11111111111111111111111111111011 //------------------------------------- // 00000000000000000000000000001011 11 printf("%d\n", a); //11 return 0; }
🚩 运行结果: 15 11
0x07 前置、后置++
📚 定义:
① 前置++:先加加,后使用;
② 后置++:先使用,再加加;
💬 代码演示:后置++的用法
int main() { int a = 10; printf("%d\n", a++); // 后置++:先使用,再++ printf("%d\n", a); // a此时已变为11 return 0; }
🚩 运行结果: 10 11
💬 代码演示:前置++的用法
int main() { int a = 10; printf("%d\n", ++a); // 前置++:先++,再使用 printf("%d\n", a); return 0; }
🚩 运行结果: 11 11
0x08 前置、后置 --
📚 定义:
① 前置--:先减减,后使用;
② 后置++:先使用,再减减;
💬 代码演示:后置 - - 的用法
int main() { int a = 10; printf("%d\n", a--); printf("%d\n", a); return 0; }
🚩 运行结果: 10 9
💬 代码演示:后置 - - 的用法
int main() { int a = 10; printf("%d\n", --a); printf("%d\n", a); return 0; }
🚩 运行结果: 9 9
0x09 强制类型转换(type)
📚 作用:强制类型转换可以把变量从一种类型转换为另一种数据类型;
📌 注意事项:
💬 代码演示:强制类型转换的用法
int main() { int a = (int)3.14; return 0; }
六、关系操作符
📌 注意事项:在编程的过程中要小心 = 和 == 不小心写错,导致的错误;
💬 代码演示:一般用于条件语句中
int main() { int a = 3; int b = 5; if(a < b) { ... } if(a == b) { ... } if(a <= b) { ... } if(a != b) { ... } return 0; }