C语言-操作符

目录

前言

操作符分类

1.算术操作符

2.移位操作符

<<  左移操作符

>>  右移操作符

3.位操作符 

&  按位与

|  按位或

^  按位异或

4.赋值操作符 

 复合赋值符

5.单目操作符 

!  逻辑反操作

~  对一个二进制按位取反 

++    --  自增、自减

(类型)  强制类型转换

*  取地址、&  解引用(注意区别 逻辑与)

sizeof()

 6.关系操作符

 7.逻辑操作符

&&  逻辑与

||    逻辑或 

 8.条件操作符

 9.逗号表达式

10.函数调用、下标引用和结构体成员

[]  下标引用操作符

()  函数调用操作符

.、->  结构体成员



前言

        首先我建议在学习使用操作符的过程中,不要死记操作符的优先级,通常我们只需要记住乘除的优先级大于加减之类简单的即可,在实际使用中,我们尽量多使用 ' () ' 来改变操作符的优先级,这样做既可以避免去背繁琐的操作符优先级,防止记错误用,还可以提高代码的可读性,对表达式的执行顺序一目了然

        操作符的学习需要结合具体实例,作者本人在学完操作符之后,在刷题的过程中发现很多操作符自己根本不会用(在解题过程中没有想到,就是常见的理解了概念,但是拿不出手),看完大佬解题巧妙使用操作符之后总是感到惊奇,本文我会尽力给出一些例题辅助学习。(例题来自课本或者常见的刷题网站)


操作符分类

1.算术操作符

2.移位操作符

3.位操作符

4.赋值操作符

5.单目操作符

6.关系操作符

7.逻辑操作符

8.条件操作符

9.逗号表达式

10.函数调用、下标引用和结构体成员

C语言的操作符大概可以分为以上类别,接下来我们依次讲解


1.算术操作符

算术操作符
    +    -    *    /    %

        + - 加减操作符等价于数学的加减
        /  除法操作符
除法操作符的两个操作数都是整数的话,执行的是整型除法
除法操作符的两个操作数只要有一个为小数,执行的是浮点型除法

现有n盒未打开的酸奶,假设小猴每h分钟能够喝完一盒酸奶,
并且它喝光一盒酸奶之前不会喝另一盒,那么经过m分钟后还有多少盒未打开的酸奶?

#include<stdio.h>
int main()
{
    float n = 0, h = 0, m = 0;
    scanf("%f%f%f", &n, &h, &m);
    int boxes = (n-(m/h));
    printf("%d", boxes);
    return 0;
}

        %  取模操作符
取模操作符的两个操作数只能是整型

其它算术操作符的两个操作数既可以是整型,也可以是浮点型

判断整数的奇偶性

int main()
{
    int i = 0;
    scanf("%d", &i);
    if(i%2 == 0)
        printf("Even\n");
    else
        printf("Odd\n");
    return 0;
}

2.移位操作符

    <<    >>

移位操作符,“位”指的是二进制位,如果对二进制不够清楚,可以参考后面的补充-原码反码补码

<<  左移操作符

规则:左边丢弃,右边补零

我们以32位状态下为例:

实际上,num的值并没有发生改变

>>  右移操作符

右移操作符分为两种,它们的移位规则并不相同:

1.逻辑移位:

        左边补零,右边丢弃

2.算术移位

        左边的符号位不变,右边丢弃

        我们可以看到当前编译器VS2022的右移操作符执行的是算术右移

实际上,执行逻辑移位还是算术移位是由编译器自己决定的

Warning:对于移位运算符,不要移动负数位

计算2的n次方

#include <stdio.h>

int main()
{
    int n = 0;
    scanf("%d", &n);
    int sum = 1;
    for (int i = 0; i < n; i++)
    {
        sum <<= 1;
    }
    printf("%d", sum);
    return 0;
}

3.位操作符 

    &   |   ^

它们的操作数必须是整数,“位”指的是二进制位,如果对二进制不够清楚,可以参考后面的补充-原码反码补码

&  按位与

规则:比较两个操作数二进制相同位置的数码,有0则0,全1为1

int a = 3;//0011
int b = 5;//0101
int c = a & b;
//c = 1    0001

统计一个整数的二进制形式数码1的个数
#include <stdio.h>
int main()
{
    int n = 0;
    int k = 0;
    scanf("%d",&n);
while(n)
{
    n &= (n-1);
    k++;
}
    printf("%d", k);
    return 0;
}

|  按位或

规则:比较两个操作数二进制相同位置的数码,有1则1,全0为0

int a = 3;//0011
int b = 5;//0101
int c = a | b;
//c =  7   0111

^  按位异或

规则:比较两个操作数二进制相同位置的数码,相异为1,相同为0

int a = 3;//0011
int b = 5;//0101
int c = a ^ b;
//c = 6    0110

不创建临时变量交换两个数的值
#include <stdio.h>

int main()
{
    int a = 3;
    int b = 4;
    //下面这种方法虽然也可以,但是a+b如果太大可以会丢失数据
    //int a = a + b - a;
    //int b = a + b - b;
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("%d %d\n", a, b);
    return 0;
}

4.赋值操作符 

        =    

赋值操作符可以给一个可修改的左值重新赋值

 赋值操作符可以连续赋值

 复合赋值符

    +=    -=    *=    /=    %=    <<=    >>=    &=    |=    ^=

5.单目操作符 

    !  逻辑反操作                               sizeof  计算操作数的类型长度(单位:字节)

    -  负值                                          --  位于操作数前面或后面作用不同

    +  正值                                         ++  位于操作数前面或后面作用不同

    &  取地址                                      ~  对一个二进制按位取反       

    *  间接访问操作符                        (类型)  强制类型转换

!  逻辑反操作

判断整数的奇偶性还可以这样写

int main()
{
    int i = 0;
    scanf("%d", &i);
    if (!(i % 2 == 0))        //  <=> i % 2 == 0 不成立 
        printf("奇数\n");
    else
        printf("偶数\n");
    return 0;
}

~  对一个二进制按位取反 

判断输入字符的类型

#include <stdio.h>
int main()
{
    char ch = 0;
    while (~scanf("%c", &ch))    // <=> while(scanf("%c", &ch) != EOF)
    {
        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
            printf("字母\n");
        else if (ch >= '0' && ch <= '9')
            printf("数字\n");
        else
            printf("其他\n");
        getchar();
    }
    return 0;
}

注意: EOF的值为 -1, 二进制形式各位均为1, 按位取反后各位上均为0, 最终结果为假, 从而结束循环

++    --  自增、自减

我们在循环语句中已经对它们不陌生了

顺序/逆序打印一个数组

#include <stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	//逆序打印
	/*for (int i = 9; i >= 0; i--)
	{
		printf("%d ", arr[i]);
	}*/
	return 0;
}

(类型)  强制类型转换

现有n盒未打开的酸奶,假设小猴每h分钟能够喝完一盒酸奶,
并且它喝光一盒酸奶之前不会喝另一盒,那么经过m分钟后还有多少盒未打开的酸奶?

#include<stdio.h>
int main()
{
    float n = 0, h = 0, m = 0;
    scanf("%f%f%f", &n, &h, &m);
    printf("%d", (int)(n-(m/h));    // float -> int 类型
    return 0;
}


字符转ASCII码

#include<stdio.h>
int main()
{
    char i = 0;
    scanf("%c",&i);
    printf("%d\n",i);    // char -> int
    return 0;
}

*  取地址、&  解引用(注意区别 逻辑与)

1    #include <stdio.h>
2    int main()
3    {
4    	int num = 10;
5    	int* p = &num;	
6    	printf("%d", *p);
7    	return 0;
8    }

注意:第5、6行,* 的作用不同

sizeof()

 6.关系操作符

        <    <=    >    >=    !=    ==

    !=    用于测试 不相等

    ==    用于测试 相等

关系操作符常用于if语句

注意不要把 " == " 写成 " = "

 7.逻辑操作符

        &&  逻辑与  、  ||  逻辑或

用法:表达式1 操作符 表达式2

&&  逻辑与

        表达式1和表达式2同时成立,返回值为真,否则为假

||    逻辑或 

        表达式1和表达式2其中之一成立,返回值为真;表达式1和表达式2都不成立,返回值为假

判断下列程序的运行结果

int main()
{
	int i = 0;
	int a = 0, b = 2, c = 3, d = 0;
	i = a++ && ++b && d++;
	//i = a++ || ++b || d++;
	printf("%d %d %d %d\n", a, b, c, d);
	return 0;
}

实际上,对于 && 如果表达式1为假,就可以判断(表达式1 && 表达式2)的结果为假了,此时计算机不再运行表达式2;对于 || 如果表达式1为真,就可以判断(表达式1 && 表达式2)的结果为真了,此时计算机不再运行表达式2

判断是否为闰年

int main() 
{
    int n = 0;
    scanf("%d", &n);
    if (n % 400 == 0 || (n % 4 == 0 && n % 100 != 0)) 
        printf("yes");
    else 
        printf("no");
    return 0;
}

 8.条件操作符

        表达式1 ? 表达式2 :表达式3

有些场合条件操作符甚至可以代替if语句

输出两个数的较大值

#include <stdio.h>

int main()
{
	int a = 0, b = 0;
	int max = 0;
	scanf("%d %d", &a, &b);
	if (a >= b)
		max = a;
	else
		max = b;
	printf("%d\n", max);
	return 0;
}


等效代码
int main()
{
	int a = 0, b = 0;
	int max = 0;
	scanf("%d %d", &a, &b);
	max = a > b ? a : b;
	printf("%d\n", max);
	return 0;
}

 9.逗号表达式

        表达式1, 表达式2, 表达式3, ..., 表达式N;

 

 

10.函数调用、下标引用和结构体成员

[]  下标引用操作符

        我们在引用数组的元素的时候最常使用的就是下标,数组名 + [下标] 可以非常便捷地使用数组的元素,[]的两个操作数是 数组名 和 下标

输入一个整型序列,判断它是否有序

int main()
{
    int i,arr[100],n,cnt1=0,cnt2=0;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%d",&arr[i]);
    }
    for(i=0;i<n-1;i++)
    {
       if(arr[i]-arr[i+1]>=0)
           cnt1++;//降序计数
       else if(arr[i]-arr[i+1]<=0)
           cnt2++;//升序计数
    }
    if(cnt1==n-1||cnt2==n-1)//一共n个数,两两相减的到n-1个结果
        printf("sorted");
    else
        printf("unsorted");
}

()  函数调用操作符

        可以接受一个或多个操作数,第一个操作数的函数名,其它操作数是传递给函数的参数

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

void main()
{
	char str1[] = "hello world";
	char str2[20] = { 0 };
	strcpy(str2, str1);
	printf("%s\n", str2);
}

main()
strcpy()
printf()

.、->  结构体成员

访问一个一个结构体的成员,可以使用下面两种形式

结构体 . 成员名

结构体指针 -> 成员名

struct S
{
	char ch;
	int id;
};

void point(struct S* ps)
{
	printf("%c\n%d", ps->ch, ps->id);
}

int main()
{
	struct S s = { 'a',1234 };
	printf("%c\n%d\n", s.ch, s.id);
	point(&s);
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

φ冰霰ξ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值