C_运算符(精讲)

2021/7/2 23:24:24

本文主要是介绍C_运算符(精讲),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

知识点1【有符号和无符号】(重要)

1、有符号数:

案例:

2、无符号数:

案例:

3、代码如何定义有符号数的方式

4、定义无符号数

5、有符号和无符号的对比(1字节为例)

有符号:

无符号:

案例:打印有符号的整型(int)、短整型(short)、长整型(long)

知识点2【进制的转换】(重要)

1、十进制 转 二进制、八进制、十六进制。(短除法)

案例1:将123转换成二进制

案例2:123转八进制

案例3:123转十六进制

2、二进制、八进制、十六进制 转 十进制 (进制的位次幂)

案例1:二进制1101转成十进制

案例2:八进制047转成十进制

案例3:十六进制0xa2转成十进制

3、八进制、十六进制 转 二进制。

八进制 转 二进制:每1位八进制 对应 3位二进制

十六进制 转 二进制:每1位十六进制 对应 4位二进制

4、二进制转八进制、十六进制

二进制 转 八进制:从右往左 每3位二进制 对应1位八进制

二进制转十六进制:从右往左 每4位二进制 对应1位十六进制

5、八进制 转 十六进制

案例:0123==001 010 011==0101 0011=0x53

6、十六进制 转 八进制

案例:0xaa==1010 1010==10 101 010==252

知识点3【原码、反码、补码】(重要)

1、无符号数据的原码、反码、补码

2、有符号数:正数的原码、反码、补码

3、有符号数:负数的原码、反码、补码

总结:

补码意义:(重要)

1、统一了0的编码

2、将减法运算变成加法运算

知识点4【计算机存储数据】(了解)

知识点5【计算机取数据】(了解)

知识点6【void类型 空类型 无类型】(重要)

知识点7【register寄存器变量】(了解)

注意:

知识点8【volatile关键字】(了解)

知识点9【const关键字】(了解)

知识点10【extern关键字】(了解)

案例:不同源文件之间

变量定义和声明区别:

知识点11【typedef关键字】(了解)

知识点12【数据的输出格式】(了解)

案例

知识点13【类型转换】(了解)

1、自动类型转换(编译器自动完成)

案例1:

signed int和unsigned int参加运算会将signed int转换成unsigned int

案例2:char、short数据只要参加运算 都将自己转换成int

2、强制类型转换(不安全)

知识点14【运算符】(了解)

1、运算符的概述

2、算术运算符

如果rand()产生一个>=0随机数,请写出产生60~100的随机数表达式

如果rand()产生一个>=0随机数,请写出产生'a'~'z'的随机字母表达式

3、复合运算符 +=         -=         *=         /=         %=

案例1:

3、关系运算符

4、逻辑运算符

1、&&逻辑与

短路特性:

2、|| 逻辑或

短路特性:

3、! 逻辑非:

5、位运算符(二进制位操作)

1、&按位与

案例:

2、|按位或

案例1:

案例2:

3、~按位取反

4、^按位异或

5、左移

6、右移 >>

综合案例:

6、条件运算符?:

案例1:键盘输入两个int类型的值 求其最大值

7、逗号运算符(了解)

8、自增自减运算符(重要)

1、概述

 2、++i --i 都是++或--在变量左边

3、i++ i-- 都是++或--在变量右边

9、优先级(重要)



知识点1【有符号和无符号】(重要)

1、有符号数:

        数据的二进制位的最高位为符号位,其他位为数据位。

        以1字节为例:xddd dddd 其中x表示符号位 d表示的是数据位

        x为0表示正数 x为1表示负数。

案例:

        +10:        0000 1010

        -10:         1111 0110

我们可以这样计算-10的二进制表达方式:

        不进行补码反码计算的二进制-10:          10001010

        进行数据位反码输出:                              11110101

        进行数据位补码输出:                              11110110

2、无符号数:

        没有符号位 全是数据位。

案例:

10:0000 1010

3、代码如何定义有符号数的方式

//第一种方式:
int data1;//默认是有符号数 (推荐)

//第二种方式:
signed int data2;//显示说明是有符号

4、定义无符号数

//唯一一种
unsigned int data;//unsigned不能省略

5、有符号和无符号的对比(1字节为例)

有符号:

1000 0000~1111 1111~0000 0000~0111 1111        (通过补码和反码运算对应到范围)

     -128   ~        -1      ~      +0       ~     +127

将-0看成-128最终1字节的有符号范围:-128~127

无符号:

0000 0000 ~1111 1111

        0        ~      255

案例:打印有符号的整型(int)、短整型(short)、长整型(long)

#include <stdio.h>

void test01(){
    int data1 = 10;
    printf("data1 = %d\n", data1);
    unsigned int data2 = 11;
    printf("data2 = %u\n", data2);

    short data3 = 12;
    printf("data3 = %hd\n", data3);
    unsigned short data4 = 13;
    printf("data4 = %hu\n", data4);

    long data5 = 14;
    printf("data5 = %ld\n", data5);
    unsigned long data6 = 15;
    printf("data6 = %lu\n", data6);
}

int main(int argc, char const *argv[]){
    test01();
    return 0;
}

知识点2【进制的转换】(重要)

二进制、八进制、十进制、十六进制

二进制:0~1 C语言无法直接显示二进制

八进制:0~7 %o输出八进制 数据表现形式 0234 必须以0开头

十进制:0~9 %d %u输出十进制 无具体的表现形式 123

十六进制:0~9 a~f %x输出十六进制 数据表现形式 0x123 必须以0x开头

void test02(){
    int data1 = 100;
    printf("data1的八进制:%#o\n", data1);   //这里#表示显示进制表示符
    printf("data1的十进制:%d\n", data1);
    printf("data1的十六进制:%#x\n", data1);
    //不同的进制 仅仅是数据的不同表现形式 在计算机中始终按二进制形式存储 数据是不变的
}

int main(int argc, char const *argv[]){
    test02();
    return 0;
}

1、十进制 转 二进制、八进制、十六进制。(短除法)

案例1:将123转换成二进制

案例2:123转八进制

案例3:123转十六进制

2、二进制、八进制、十六进制 转 十进制 (进制的位次幂)

案例1:二进制1101转成十进制

案例2:八进制047转成十进制

案例3:十六进制0xa2转成十进制

3、八进制、十六进制 转 二进制。

八进制 转 二进制:每1位八进制 对应 3位二进制

十六进制 转 二进制:每1位十六进制 对应 4位二进制

4、二进制转八进制、十六进制

二进制 转 八进制:从右往左 每3位二进制 对应1位八进制

1100 0011 == 11 000 011 ==0303

二进制转十六进制:从右往左 每4位二进制 对应1位十六进制

5、八进制 转 十六进制

案例:0123==001 010 011==0101 0011=0x53

6、十六进制 转 八进制

案例:0xaa==1010 1010==10 101 010==252

知识点3【原码、反码、补码】(重要)

原码:数据的二进制形式 就是原码

比如:以一个字节 10---->0000 1010

1、无符号数据的原码、反码、补码

原码==反码==补码

10原码:0000 1010 反码:0000 1010 补码:0000 1010

2、有符号数:正数的原码、反码、补码

原码==反码==补码

+10原码:0000 1010 反码:0000 1010 补码:0000 1010

3、有符号数:负数的原码、反码、补码

-10:

原码:1000 1010

反码:符号位不变 其他位按位取反 1111 0101

补码:反码+1 1111 0110

案例:

无符号32:原码0010 0000 反码0010 0000 补码0010 0000

         +32:原码0010 0000 反码0010 0000 补码0010 0000

          -32:原码1010 0000 反码 1101 1111 补码1110 0000

总结:

        1、无符号 在计算机中存储的是补码(原码)

        2、有符号 正数在计算机中存储的是补码(原码)

        3、有符号 负数在计算机中存储的是补码

补码意义:(重要)

1、统一了0的编码

        +0:原码0000 0000 反码0000 0000 补码:0000 0000

        -0:原码1000 0000 反码1111 1111 补码:0000 0000

2、将减法运算变成加法运算

没有补码:10-6

        10:0000 1010        

        -6 :1000 0110

        -------------------------

              1001 0000==-16(错误)

用补码计算:

         10:0000 1010

         -6 :1111 1010

        --------------------

             0000 0100==4(正确)

知识点4【计算机存储数据】(了解)

无符号 在计算机中存储的是补码(原码)

有符号 正数在计算机中存储的是补码(原码)

有符号 负数在计算机中存储的是补码

当以十六进制给变量赋值的时候 计算机存储的是原码。

当以八进制给变量赋值的时候 计算机存储的是原码。

void test03(){
    char ch = 10;
    printf("ch = %#x\n", ch);

    ch = -10;
    printf("ch = %#x\n", ch);

    ch = 0x86;
    printf("ch = %#x\n", ch);
}

int main(int argc, char const *argv[]){
    test03();
    return 0;
}

/**
    ch = 0xa
    ch = 0xfffffff6
    ch = 0xffffff86
 */

知识点5【计算机取数据】(了解)

无符号提取:内存原样提取 %u %hu %lu提取 %o %x原样提取

(signed)有符号提取:%d %hd %ld 有符号提取 提取公式如下:

首先查看内存的二进制的最高位,如果是1,说明内存数据的是某一个负数的补码,就必须计算出原码(符号位不变,其他位取反,+1) 然后输出。如果是0,内存原样输出

void test04(){
    unsigned char ch1 = 10; //0000 1010 内存存储的数据
    printf("ch1 = %u\n", ch1);  //10

    char ch2 = 0xaa;        //1010 1010 内存存储的数据
    printf("ch2 = %d\n", ch2);  //-86
    printf("ch2 = %#x\n", ch2);  //0xffffffaa
    printf("ch2 = %u\n", ch2);  //4294967210
}

int main(int argc, char const *argv[]){
    test04();
    return 0;
}

知识点6【void类型 空类型 无类型】(重要)

void test05(){
    void test05(){
    //void不能定义普通变量
    //void data; 系统没办法根据void了解为data开辟多大空间
    printf("%d\n", sizeof(void));//1,由编译器决定void的大小,编译器不同结果不同
}

int main(int argc, char const *argv[]){
    test05();
    return 0;
}
    printf("%d\n", sizeof(void));//1,由编译器决定void的大小,编译器不同结果不同
}

int main(int argc, char const *argv[]){
    test05();
    return 0;
}

void                  不能定义普通变量
void data;         系统没办法根据void了解为data开辟多大空间

void可以定义指针变量 (后续再讲)

知识点7【register寄存器变量】(了解)

当某个变量被高频率使用的时候 编译器会将该变量设置为寄存器变量(编译器决定)

但是用户可以通过 register手动设置变量为寄存器变量

register int data;

注意:

1、不能对寄存器变量 取地址

地址:指的是内存的逻辑地址(物理内存虚拟出来分配给进程的地址4G),寄存器变量是在寄存器中。二者不是同一回事

&data表示取data的内存地址

void test06(){
    register int data = 10;
    printf("%p\n", &data);  //err
}

int main(int argc, char const *argv[]){
    test06();
    return 0;
}

2、register int data 只是建议将data放入寄存器,如果当前寄存器用完 是放不进去的。

3、如果一个变量data没有register修饰 但是data被高频繁使用 编译器也会将其放入寄存器

知识点8【volatile关键字】(了解)

volatile关键字:防止编译器优化、强制访问内存操作。

volatile int data=10;
data=11;
data=12;
data=13;
data=14;
//如若不加volatile,经编译器优化后将只执行data=14;
//经过volatile,禁止编译器优化,会逐句执行

知识点9【const关键字】(了解)

const修饰变量为只读;

//data为只读变量  而不是常量
const int data=10;//data为只读  除了初始化 不允许被赋值

暂时先了解,后面会讲

知识点10【extern关键字】(了解)

extern:声明变量或函数外部源文件

声明变量或函数:

如果是先使用 后定义 就需要提前extern声明。

//提前声明,不要负责,告知编译器如果下方遇到data清通过
extern int data;    //显式声明变量
void test02(){
    printf("data = %d\n", data);
}
int data = 10;

案例:不同源文件之间

fun.c

//定义
int num = 100;

main.c

//声明该变量存在 请通过编译
extern int num;

void test03()
{
   printf("num = %d\n", num);//使用
}

变量定义和声明区别:

变量的定义:系统给变量开辟空间,初始化,让变量存在。

变量的声明:对已有的变量进行说明(该变量已经存在,请通过变量),不会为变量开辟空间, 不要对变量赋值。尽量使用extern修饰。

知识点11【typedef关键字】(了解)

typedef:为已有的类型 取个别名(类型名),不能创建新的类型。旧的类型名任然可用。

步骤:

        1、给什么类型取别名 先用这个类型先定义一个普通变量。

        2、用别名 替换 变量名。

        3、在整个表达式前面 加上typedef。

案例:将int取个别名INT32

//INT32 和 int等价
typedef int INT32;
void test04()
{
   INT32 data1 = 10;
   int data2 = 20;
   printf("%d %d\n", data1, data2);//10 20
}

typedef作用:方便使用类型,便于工程移植。

知识点12【数据的输出格式】(了解)

案例

void test05()
{
   printf("#################\n");
   //默认右对齐
   printf("##%3d##\n", 12);
   printf("##%3d##\n", 1234);//%3d中 3格式无效

   //不足左边补0
   printf("##%03d##\n", 12);
   printf("##%03d##\n", 1234);//%3d中 3格式无效

   //左对齐
   printf("##%-3d##\n", 12);
   //%-03d无效格式
   printf("##%-03d##\n", 12);

   //%5.2f  5整个数据的位宽(包含小数点) 2小数部分位数
   printf("##%5.2f##\n", 3.141592f);
}

知识点13【类型转换】(了解)

两种转换方式:自动类型转换(安全)、强制类型转换(不安全)

1、自动类型转换(编译器自动完成)

一般在遇到不同类型数据参加运算的时候才会发生,除了char、short以外。

char short只要参与运算 都会将char short转成int

防止精度丢失。防止数据溢出。

案例1:

signed int和unsigned int参加运算会将signed int转换成unsigned int

void test08(){
    int data1 = -10;
    unsigned int data2 = 6;

    //将data1转化为无符号数 > 0 data2==6 >0 所以data1+data2>0
    if(data1 + data2 > 0){
        printf("大于0\n");//正确
    }
    else if(data1 + data2 < 0){
        printf("小于0\n");
    }
}

int main(int argc, char const *argv[]){
    test08();
    return 0;
}

拓展分析data1为-10那么转成无符号是多少呢?(答案是-10的补码)

data1的内存存储的是-10的补码:1111 1111 1111 1111 1111 1111 1111 0110

当把data1转成无符号数,其实就是取内存的原样数据

void test09(){
    int data1 = -10;
    unsigned int data2 = 6;
    printf("%d\n", data1 + data2); //-4
}

int main(int argc, char const *argv[]){
    test09();
    return 0;
}

既然打印出来的data1+data2=-4为什么上面的代码,判断data1+data2>0正确呢?

这是因为我们的数据解析方式不同:

        上面的代码我们是按照unsigned int方式进行解析,得出来的数据只能是正数

        下面的代码我们用%d打印即我们指定用有符号的signed int方式解析,结果自然为负数

接下来展示一下data1+data2的计算方式:

data1无符号是:1111 1111 1111 1111 1111 1111 1111 0110

data2无符号是:0000 0000 0000 0000 0000 0000 0000 0110

--------------------------------------------------------------------------------------

                          1111 1111 1111 1111 1111 1111 1111 1100

%d就会查看最高位是否为1,上面的数是某个数的补码,转化原码输出

        反码 1000 0000 0000 0000 0000 0000 0000 0011

                + 0000 0000 0000 0000 0000 0000 0000 0001

-----------------------------------------------------------------------------

                1000 0000 0000 0000 0000 0000 0000 0100==-4

案例2:char、short数据只要参加运算 都将自己转换成int

void test10(){
    char ch = 10;
    short s = 20;
    printf("sizeof(char) = %d\n", sizeof(char));
    printf("sizeof(short) = %d\n", sizeof(short));
    printf("sizeof(ch + ch) = %d\n", sizeof(ch+ch));
    printf("sizeof(short + short) = %d\n", sizeof(s+s));
    printf("sizeof(char + short) = %d\n", sizeof(ch+s));
}

int main(int argc, char const *argv[]){
    test10();
    return 0;
}

/*
sizeof(char) = 1
sizeof(short) = 2
sizeof(ch + ch) = 4
sizeof(short + short) = 4
sizeof(char + short) = 4
*/

2、强制类型转换(不安全)

(类型说明符) (表达式)

void test11(){
    float f = 3.14f;
    int x =0;

    //=赋值运算符 必须要求左右两边类型匹配
    //强制类型转换 只是临时的转换 不会更改f的类型
    x = (int)f;
    printf("x = %d, f = %f\n", x, f);
}

//x = 3, f = 3.140000

int main(int argc, char const *argv[]){
    test11();
    return 0;
}

知识点14【运算符】(了解)

1、运算符的概述

用算术运算符将运算对象(也称操作数)连接起来的、符合C语法规则的式子,称为C算术表达式 运算对象包括常量、变量、函数返回值等

如果运算符只有一个运算对象 单目运算符 i++

如果运算符只有两个运算对象 双目运算符 10+10

如果运算符只有三个运算对象 三目运算符 ?:

2、算术运算符

+         -         *         /         %         +=         -=         *=         /=         %=

1、取整 / 如果运算对象是实型 那就是除

5/3 == 1
2/3 == 0

2、取余 %

5%3 == 2

如果想判断n是否能被3整除的表达式

if(n%3 == 0)

m>=0 那么 m%n取余的范围

0~n-1

如果rand()产生一个>=0随机数,请写出产生60~100的随机数表达式

rand()%41+60

如果rand()产生一个>=0随机数,请写出产生'a'~'z'的随机字母表达式

rand()%26+'a'

3、复合运算符 +=         -=         *=         /=         %=

a *= b -----> a=a*b

a += b -----> a=a+b

注意:一定要将=号右边看成一个整体‘

int a = 3;
a *= 2+5;//a = a * (2+5)
printf("a = %d\n", a);

案例1:

int a = 3;
a += a-= a*=a;//从右往左计算
printf("a = %d\n", a);

3、关系运算符

(>、<、= =、>=、!=)

4、逻辑运算符

&&逻辑与 || 逻辑或 !逻辑非

1、&&逻辑与

A && B :只有当AB同时为真 A && B这个整个表达式才为真,只要AB有一个为假 结果都为假

短路特性:

逻辑与的"短路特性":如果A为假 那么整个表达式结果已经为假 那么计算机就不会再去判断B的真假,这种特性就叫逻辑与的"短路特性"

void test12(){
    int a = 5;
    a>10 && printf("hehe\n");
}

2、|| 逻辑或

A || B:只要AB中有一个为真 A || B整个表达式结果为真, 只要当AB同时为假的时候 结果才为假。

短路特性:

逻辑或的"短路特性":如果A为真 B将不会判断

void test13(){
    int a = 50;
    a>10 || printf("hehe\n");
}

案例:假如有两变量,data1获取银行卡号, data2获取密码,请写出:data1和data2只要有一个不是数值就判断非法输入。假定Number是一个测试数值的函数

提示:Number(测试的数值)函数是判断数值的 如果为数值返回true 非数值返回false

if( (Number(data1)==false)  ||  (Number(data2)==false) )
{
    printf("提示非法输入\n");
}

3、! 逻辑非:

!真 == 假 !假 == 真

注意:在c语言中 0为假 其他都为真(1, 10 , 200, -50)

void test14(){
    printf("%d\n", !0); //1
    printf("%d\n", !1); //0
    printf("%d\n", !-1); //0
}
if( !Number(data1)  ||  !Number(data2) )
{
    printf("提示非法输入\n");
}
else
{
    printf("输入合法的数据,密码匹配中\n");
}

5、位运算符(二进制位操作)

&按位与 | 按位或 ~按位取反 ^按位异或 >二进制右移

1、&按位与

语法:有0为0 全1为1

特点:和0相与为0 和1相与保持不变

应用场景:将指定的位清0

   1100 1100

& 1111 0000

-------------------------

    1100 0000

案例:

        假如data为一个字节,将data的第2、3位清0,其他为保持不变。

注意:从右往左 :7 6 5 4 3 2 1 0

data = data & 1111 0011;
正确的写法:
data = data & 0xf3;

2、|按位或

语法:有1为1 全0为0

特点:和1或置1 和0或 保持不变

应用场景:将固定的位置1

  1100 1100

| 1111 0000

-----------------------

  1111 1100

案例1:

        假如data为一个字节,将data的第2、3位置1,其他为保持不变

data = data | 0000 1100
正确的写法:
data = data | 0x0c;
data |= 0x0c;

案例2:

        假如data为一个字节,将data的第2、3位置1,第5、6位清0.其他为保持不变

第一种方式:
data = data | 0000 1100 & 1001 1111;
第二种方式:
data = data | 0000 1100;
data = data & 1001 1111;
正确写法:
data = data | 0x0c & 0x9f;

3、~按位取反

        ~1010 1010 == 0101 0101

4、^按位异或

语法:相同为0 不同为1

特点:和1异或发生翻转 和0异或保持不变

应用场景:将固定位发生翻转

        1100 1100

     ^ 1111 0000

        -----------------------

        0011 1100

    ^ 1111 0000

        -----------------------

        1100 1100

5、左移

        左边丢弃 右边补0

案例:

加入data = 0x01==0000 0001 左移0位:0000 0001 第0位为1 == 1

加入data = 0x01==0000 0001 左移1位:0000 0010 第1位为1 ==2

加入data = 0x01==0000 0001 左移2位:0000 0100 第2位为1 ==4

加入data = 0x01==0000 0001 左移3位:0000 1000 第3位为1 ==8

。。。。。

加入data = 0x01==0000 0001 左移6位:0100 0000 第6位为1 ==64

加入data = 0x01==0000 0001 左移7位:1000 0000 第7位为1 ==128

假设data = 0x01 左移n位(0~7) data = data * 2^n

6、右移 >>

无符号数:右边丢弃 左边补0

有符号数:

        正数:右边丢弃 左边补0

        负数:右边丢弃 左边补1 算术右移

        负数:右边丢弃 左边补0 逻辑右移

算术右移、逻辑右移:由编译器决定。

案例:测试编译是算术右移还是逻辑右移

void test15(){
    char data = -10; //-10的补码 0x1111 0110
    printf("右移前的数据: %#x\n", data);
    data = data >> 4;
    //如果是逻辑右移:0000 1111 = 0x0f
    //如果是算术右移:1111 1111 = 0xff
    printf("移动后的数据: %#x\n", data);
}

int main(int argc, char const *argv[]){
    test15();
    return 0;
}

综合案例:

        假如data为一个字节,将data的第2、3位置1,第5、6位清0.其他为保持不变

//将2、3为置1
data = data | 0000 1100;
0000 1100 == 0000 1000 | 0000 0100;
0000 1100 == 0000 0001<<3 | 0000 0001 <<2;
0000 1100 == 0x01<<3 | 0x01 <<2;
推荐的写法:data = data | (0x01<<3 | 0x01<<2);
data |= (0x01<<3 | 0x01<<2);

//将5、6位清0
data = data & 1001 1111;
1001 1111 == ~(0110 0000)== ~(0100 0000 | 0010 0000) 
          ==~(0000 0001<<6 | 0000 0001<<5)
          ==~(0x01<<6 | 0x01<<5)
推荐的写法:data = data & ~(0x01<<6 | 0x01<<5) ;
data &= ~(0x01<<6 | 0x01<<5);

6、条件运算符?:

A?B:C;

如果A表达式成立,整个表达式的值B,

如果A表达式不成立,整个表达式的值C

void test16(){
    printf("%d\n", 3>5?10:20);
}

案例1:键盘输入两个int类型的值 求其最大值

void test17(){
    int data1 = 0;
    int data2 = 0;
    printf("请输入两个int类型的值:");
    scanf("%d %d", &data1, &data2);
    printf("最大值为:%d\n", data1>data2?data1:data2);
}

int main(int argc, char const *argv[]){
    test17();
    return 0;
}

7、逗号运算符(了解)

逗号运算符是所有运算符中级别最低的,因此,下面两个表达式的作用是不同的:

void test18(){
    int num = 0;
    num = 1,2,3;
    printf("num = %d\n", num);      //1
    
    int data = 0;
    data = (1, 2, 3);
    printf("data = %d\n", data);    //3
}

int main(int argc, char const *argv[]){
    test18();
    return 0;
}

        其实,逗号表达式无非是把若干个表达式“串联”起来。即逗号表达式纯粹就是为了在只能写一条表达式的地方写多条表达式而设计的,根据c++ Primer,用得最多的地方就是for循环,例如:

8、自增自减运算符(重要)

        ++i、--i、i++、i--

1、概述

++i或i++独立作为一条语句,是完全一样的。

++i ==> i=i+1; --i ==> i=i-1;

i++ ==> i=i+1; i-- ==> i=i-1;

void test19(){
    int i = 5;
    ++i;
    printf("++i = %d\n", i);

    int j = 5;
    j++;
    printf("j++ = %d\n", j);
}

 2、++i --i 都是++或--在变量左边

void test20(){
    int i = 5;
    int j = 0;

    j = ++i;
    printf("i = %d, j = %d\n", i, j); //i=6 j=6
}

3、i++ i-- 都是++或--在变量右边

注意:先试用 后加减

void test21(){
    int i = 5;
    int j = 0;

    j = i++;
    printf("i = %d, j = %d\n", i, j); //i=6 j=5
}

9、优先级(重要)

级别数值越小 越优先执行

如果优先级一样就要看 结合方向

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

--

()

圆括号

(表达式)/函数名(形参表)

--

.

成员选择(对象)

对象.成员名

--

->

成员选择(指针)

对象指针->成员名

--

2

-

负号运算符

-表达式

右到左

单目运算符

~

按位取反运算符

~表达式

++

自增运算符

++变量名/变量名++

--

自减运算符

--变量名/变量名--

*

取值运算符

*指针变量

&

取地址运算符

&变量名

!

逻辑非运算符

!表达式

(类型)

强制类型转换

(数据类型)表达式

--

sizeof

长度运算符

sizeof(表达式)

--

3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

%

余数(取模)

整型表达式%整型表达式

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

5

<< 

左移

变量<<表达式

左到右

双目运算符

>> 

右移

变量>>表达式

6

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

小于

表达式<表达式

<=

小于等于

表达式<=表达式

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1?

表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

--

/=

除后赋值

变量/=表达式

--

*=

乘后赋值

变量*=表达式

--

%=

取模后赋值

变量%=表达式

--

+=

加后赋值

变量+=表达式

--

-=

减后赋值

变量-=表达式

--

<<=

左移后赋值

变量<<=表达式

--

>>=

右移后赋值

变量>>=表达式

--

&=

按位与后赋值

变量&=表达式

--

^=

按位异或后赋值

变量^=表达式

--

|=

按位或后赋值

变量|=表达式

--

15

逗号运算符

表达式,表达式,…

左到右

--



这篇关于C_运算符(精讲)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程