C语言中操作符的总结

今天我们就来总结总结我们C语言中的操作符吧,首先大家能想起来的操作符都有哪些呢?
我们大家可能都知道常见的算术运算符,关系运算符与逻辑运算符,但除了这些之外,还有一些用于完成特殊任务的运算符,比如位运算符。这些操作符虽然看起来很简单,大家很容易理解它的浅层意思,但它的用法特别多,一不小心我们就掉进坑里了,今天我就谈一下我对它的理解吧,如果有什么不正确的地方,也请大家指出来,我们可以互相讨论讨论。

算术操作符

我们知道的算术操作符有:“+”,“-”,“*”,“/”,“%”。
“+”,“-”和“/”都非常的简单,那我们就先来看看“%”操作符吧,在这里我们要注意的是,除了“%”操作符之外,其他几个操作符都可用于整数和浮点数,“%”操作符的两个操作数必须都为整数,返回的是整除之后的余数。“/”是当两个数都为整数的时候,为整数除法,只要其中有一个是浮点型,就是浮点型除法。
我们就来看一个“%”简单的例子吧:

#include<stdio.h>
int main()
{
   int n = 6.0 % 3.0;
   return 0;
}

很显然我们这个程序是编译不过去的,因为“%”的两个数必须是整型。

移位操作符

移位操作符其实又叫二进制移位操作符,是对一个数的二进制位(补码)进行左移右移,“<<”—左移操作符,“>>”—右移操作符。
左移eg:

include<stdio.h>
int main()
{
   int n = 10;//00000000000000000000000000001010
   int m = n<<1;
   printf("%d\n",m);
   printf("%d\n",n);
   return 0;
}

这里写图片描述
代码的运行结果是:
m=20,n=10
从结果我们可以看出n其实并没有变,m是它左移一位之后的结果,我们可以总结出左移就是左边丢弃,右边补0,经过多组代码测试,我们可以发现向左移一位,有乘2的效果
右移eg:

#include<stdio.h>
int main()
{
   int n = 10;//00000000000000000000000000001010
   int m = n>>1;
   printf("%d\n",m);
   printf("%d\n",n);
   return 0;
}

这里写图片描述
运行结果是:
m=5,n=10
那同样的我们也可以得出一个结论:右移一位,有除2的效果
右移又分为算术右移逻辑右移,到底用的是哪一种右移方式呢,是由我们编译器决定的。
算术右移:右边丢弃,左边补原符号位。
逻辑右移:右边丢弃,左边补0。
这就是移位操作符,但不管怎么说,移位对被移位的数本身是不会产生影响的。

位操作符

位操作符有:& //按位与,| //按位或,^ //按位异或(两个二进制位相同为0,相异为1)
“&”eg:

include<stdio.h>
int main()
{
   int n = -1;//10000000000000000000000000000001
           //反码11111111111111111111111111111110
           //补码11111111111111111111111111111111
   int m = -3;//10000000000000000000000000000011
           //反码11111111111111111111111111111100
           //补码11111111111111111111111111111101
   int k = n & m;//我们是用补码进行运算
   //11111111111111111111111111111111
   //&
   //11111111111111111111111111111101
   //=
   //11111111111111111111111111111101(补码)--(-3)
   printf("%d",k);
   return 0;
}

运行结果是k=-3
“|”eg:

include<stdio.h>
int main()
{
   int n = -1;//10000000000000000000000000000001
           //反码11111111111111111111111111111110
           //补码11111111111111111111111111111111
   int m = -3;//10000000000000000000000000000011
           //反码11111111111111111111111111111100
           //补码11111111111111111111111111111101
   int k = n | m;//我们是用补码进行运算
   //11111111111111111111111111111111
   //|
   //11111111111111111111111111111111
   //=
   //11111111111111111111111111111111(补码)--(-1)
   printf("%d",k);
   return 0;
}

运行结果是:k=-1
“^”eg:

#include<stdio.h>
int main()
{
   int a = 3;// 0011
   int b = 10;//1010
           ^  //1001(9)
   int k = a ^ b;
   printf("%d\n",k);
   return 0;

}

运行结果是:k=9

赋值操作符

”=“这是最简单的一个赋值符了,我们还有很多复合赋值操作符:+=,-=,*=,/=,%=,>>=,<<=,&=,|=,^=,这些都很简单,没什么可讲的。

单目操作符

! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
– 前置,后置–
++ 前置,后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
”!“ eg:

#include<stdio.h>
int main()
{
   int n=10;
   printf("%d",!n);
   return 0;
}

我们这里的输出结果是:0,因为10是真,!10就是假,所以输出0。
”&“ eg:

#include<stdio.h>

int main()
{
    int a = 1;
    printf("%p\n", &a);

    return 0;
}

这里写图片描述
我们可以看到这里我们输出的是a的地址。
”sizeof()“ eg:

int main()
{
    short s = 3;
    int a = 10;
    printf("%d\n", sizeof(s = a + 3));//2
    printf("%d\n", s);//3

    return 0;
}

在这里我们看到的结果为什么回事2和3呢,因为sizeof()中的表达式不进行运算,所以s的值未被改变,sizeof()求得是与s的类型有关,与它的表达式无关。

sizeof和数组

eg:

#include<stdio.h>

void test1(int arr[10])
{
    printf("%d\n", sizeof(arr));
}

void test2(char ch[10])
{
    printf("%d\n", sizeof(ch));
}

int main()
{
    int arr[10] = { 0 };
    char ch[10] = { 0 };
    printf("%d\n", sizeof(arr));//(1)
    printf("%d\n", sizeof(ch));//(2)
    test1(arr); //(3)
    test2(ch); //(4)


    return 0;
}

这里(1)是40,(2)是10,因为数组名放进sizeof()中代表的是计算整个数组的大小,而(3)和(4)的结果是4,因为它计算的是指针的大小,指针的大小是4个字节。

“~” eg:

int main()
{
    int a = 0;
    printf("%d\n", ~a);

    return 0;
}

我们在这里得到的结果是-1,为什么会是-1呢,因为我们是对它的补码按位取反,得到的也是补码。
“++”和“–”都很简单,我们就简单的看一个例子吧:

int main()
{
    int a = 1;
    int b = a--;
    printf("%d\n", a);//0
    printf("%d\n", b);//1

    return 0;
}

“*”eg:

#include<stdio.h>

int main()
{
    int num = 10;
    int* p = &num;
    *p = 20;
    printf("%d\n", num);

    return 0;
}

这里输出的结果是20,因为*p就是num的值,改变*p就是间接改变num的值。
“(类型)”eg:


#include<stdio.h>

int main()
{
    int num = (int)3.14;
    printf("%d\n", num);

    return 0;
}

这里的输出结果是3,3.14是浮点型,没办法赋值给整型,所以我们要对它强制类型转换,把它转成整型。

关系操作符

== 用于测试“相等”
<
<=
!= 用于测试“不相等”
>
大于等于
这些操作符都特别简单,没什么可说的,但我们要注意的是“==”这个操作符
eg:

x=get_value();
if(x=5)
    //处理事务

这里我们看起来好像是x如果等于5就执行事务处理,实际上代码不是这个意思,如果我们将判断的==搞成了赋值的=,那么这个事务无论x是多少都会执行了。
警告
如果在编程过程中,我们不小心将==写出=,造成的后果是非常严重的。

逻辑操作符

&&—–逻辑与
|| —–逻辑或

“&&”eg:

#include<stdio.h>

int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ && ++b && d++;

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


    return 0;
}

这里的输出结果是:1 2 3 4,这是为什么呢?
因为我们这里的a是后置++,先使用再自加,a是0,所以&&后边的表达式直接就不用计算了,b,c,d的值没有改变,然后a再进行自加。
如果刚开始我们让a=1,输出的结果就是:2 3 3 5
因为a为1,是真,所以我们要进行后边的表达式,a自加变成2,然后b也要进行自加,a++&&++b为真就相当于1,因为是逻辑与,所以后边也要进行运算,d进行自加。

“||”eg:

#include<stdio.h>

int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ || ++b || d++;

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


    return 0;
}

我们这里的运行结果是:1 3 3 4
因为是逻辑或,所以a为假时,后边的表达式要进行计算,b自加,a在使用之后要自加,前边为真了,所以后边的d++不用进行计算了。

条件操作符

exp1 ? exp2 : exp3
eg:


#include<stdio.h>

int main()
{
    int a = 0;
    int b = 3;
    int max = a > b ? a : b;
    printf("%d\n", max);

    return 0;
}

这里的输出的结果是3,max = a > b ? a : b的意思是如果a大于b,把a赋给max,如果a>b不成立,则把b赋给max。

逗号表达式

exp1,exp2,exp3,……,expN
逗号表达式就是用逗号隔开的多个表达式,从左向右依次进行,整个表达式的结果是最后一个表达式的结果

eg:

#include<stdio.h>

int main()
{
    int a = 1;
    int b = 2;
    int c = (a > b, a = b + 10, a, b = a + 1);
    printf("%d\n", c);

    return 0;
}

运行结果是:13

下标引用,函数调用和结构成员

下标引用操作符:[],有两个操作数
eg:

#include<stdio.h>

int main()
{
    int i = 0;
    int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        printf("%d\n", arr[i]);
    }
    return 0;
}

函数调用操作符:(),至少接收一个操作数
eg:

#include<stdio.h>

void test()
{
    printf("哈哈\n");
}

void print(int n)
{
    printf("%d\n", n);
}

int main()
{
    int n = 0;
    test();
    print(3);

    return 0;
}

访问一个结构的成员操作符:.结构体.成员名 ; ->结构体指针->成员名
eg:

#include<stdio.h>
#include<string>

struct Stu
{
    char name[20];
    int age;
    char sex[5];
    char tele[12];
};
int main()
{
    struct Stu s;
    strcpy(s.name, "lisi");
    s.age = 20;
    strcpy(s.sex, "男");
    printf("%s\n", s.name);
    printf("%d\n", s.age);
    printf("%s\n", s.sex);

    return 0;
}
#include<stdio.h>
#include<string>

struct Stu
{
    char name[20];
    int age;
    char sex[5];
    char tele[12];
};
int main()
{
    struct Stu s;
    struct Stu* ps = &s;
    strcpy((*ps).name, "zhangsan");
    ps->age = 20;
    strcpy((*ps).sex, "男");
    printf("%s\n", s.name);
    printf("%d\n", s.age);
    printf("%s\n", s.sex);

    return 0;
}

当我们定义了一个结构体的指针时,我们可以用箭头来找这个结构体成员
当给一个结构体变量时,我们用.来找结构体成员

好了,今天呢,我们就把我们的所以的操作符都总结完了。

猜你喜欢

转载自blog.csdn.net/huaijiu123/article/details/79760904