【维生素C语言】第五章 - 操作符(二)

简介: 本章将对C语言操作符进行深度的讲解,将每种操作符都单独拿出来精讲。最后添加了些简单的练习题,并配有详细解析。

四、赋值操作符


0x00 概览


e990045f9c82c093f05ff908e8e18637_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81MDUwMjg2Mg==,size_16,color_FFFFFF,t_70.png

📚  用法:用来重新赋值一个变量的值;

91abe7489c56735013520595253e1efb_20210527131330488.png

0x01 一般赋值

📚  赋值方法:

e15929e1497124fb13add6b6fb9483ca_20210527134309909.png

💬 赋值操作符是个很棒的操作符,它可以让你得到一个你之前不满意的值:


int main()
{
    int weight = 120; // 体重120,不满意,我要变瘦点!
    weight = 89; // 不满意就赋值~
    double salary = 10000.0; // 我:老板!我要加薪!
    salary = 20000.0; // 老板:好的,没有问题!
    return 0;
}

0x02 连续赋值

📚  定义:连续赋值(continuous assignment),即一次性赋多个值;


📜  建议:建议不要使用连续赋值,会让代码可读性变差,而且还不容易调试;

772aa8c00b6f81599e635b2ba7d3016e_20210527134351587.png

💬  代码演示:连续赋值的使用方法;


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 概览

❓  什么是单目操作符?


💡  在运算中只有一个操作数的操作符,叫做单目操作符;

2cdbbfc2e2838bdd36bce9e03440be73_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81MDUwMjg2Mg==,size_16,color_FFFFFF,t_70.png

0x01 逻辑反操作 !

📚  作用:可以让真变为假,也可以让假变为真;

c9c67332e99394935279d39a5488398f_20210527134225991.png

💬 逻辑反操作的用法:


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 负值 -

📚  作用:把一个数置为负数;

f48f2547f773eebb48b0c21dc0fb0c5b_20210527134213780.png

💬 负值的用法:

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 取地址操作符 & 与 解引用操作符 *

1a8e127f197f676301979b3ebf92fd0e_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81MDUwMjg2Mg==,size_16,color_FFFFFF,t_70.png

📚  理解:


     ① 取地址操作符可以理解为取快递;


     ② 解引用操作符可以理解为拆快递;


     (指针章节会详解)


💬 用法演示:


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( )

📚 作用:计算变量所占内存空间的大小,单位是字节;

05113991221ca66a523f5cff1e3634c8_20210527141615998.png

📌 注意事项:


     ① 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 括号中的表达式不参与运算!

b34008df67128554054fa7c1bcaf2d6a_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81MDUwMjg2Mg==,size_16,color_FFFFFF,t_70.png

💬 下列代码输出后 (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;

9ace35f9dd6fda670c42a57f814cc201_20210527143644664.png

📌  注意事项:


     ① 按位取反,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)

📚  作用:强制类型转换可以把变量从一种类型转换为另一种数据类型;

a676dd92f9a064469dc60323c44e828e_2021052714441371.png

📌  注意事项:

ccbf70f74d32d16f705b4fd6e32296ef_20210527144520850.png

💬 代码演示:强制类型转换的用法


int main()
{
    int a = (int)3.14;
    return 0;
}

六、关系操作符


📌  注意事项:在编程的过程中要小心 = 和 == 不小心写错,导致的错误;

c69206d48dd57058dbb0b826aa038b0a_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81MDUwMjg2Mg==,size_16,color_FFFFFF,t_70.png

💬 代码演示:一般用于条件语句中


int main()
{
    int a = 3;
    int b = 5;
    if(a < b) {
        ...
    }
    if(a == b) {
        ...
    }
    if(a <= b) {
        ...
    }
    if(a != b) {
        ...
    }
    return 0;
}
相关文章
|
2月前
|
存储 C语言 索引
【C语言篇】操作符详解(下篇)
如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏运算。
|
2月前
|
程序员 编译器 C语言
【C语言篇】操作符详解(上篇)
这是合法表达式,不会报错,但是通常达不到想要的结果, 即不是保证变量 j 的值在 i 和 k 之间。因为关系运算符是从左到右计算,所以实际执⾏的是下⾯的表达式。
|
2月前
|
C语言
C语言操作符(补充+面试)
C语言操作符(补充+面试)
39 6
|
2月前
|
存储 编译器 C语言
十一:《初学C语言》— 操作符详解(上)
【8月更文挑战第12天】本篇文章讲解了二进制与非二进制的转换;原码反码和补码;移位操作符及位操作符,并附上多个教学代码及代码练习示例
50 0
十一:《初学C语言》—  操作符详解(上)
|
3月前
|
C语言
五:《初学C语言》— 操作符
本篇文章主要讲解了关系操作符和逻辑操作符并附上了多个代码示例
37 1
五:《初学C语言》—  操作符
|
4月前
|
C语言
C语言逻辑操作符的短路问题
C语言逻辑操作符的短路问题
|
4月前
|
编译器 C语言
【C语言】:中移位操作符,位操作符详运算规则详解
【C语言】:中移位操作符,位操作符详运算规则详解
31 1
|
4月前
|
算法 C语言
【C语言】:巧用移位操作符,位操作符解决问题
【C语言】:巧用移位操作符,位操作符解决问题
29 0
|
4月前
|
编译器 C语言
【C语言】:sizeof操作符的使用和各种常见数据类型的大小
【C语言】:sizeof操作符的使用和各种常见数据类型的大小
43 0
|
4月前
|
编译器 C语言 C++
下一篇
无影云桌面