c语言学习(操作符详解)

操作符的分类:

目录

算术操作符:

移位操作符:

原码反码补码

位操作符:

赋值操作符:

单目操作符:

关系操作符:

逻辑操作符:

条件操作符:

逗号表达式:

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


算术操作符:

+        -        *        /        %

1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数
% 操作符的两个操作数必须为整数。返回的是整除之后的余数
%操作符的被除数不能是0,否则就会报错

#include <stdio.h>
int main()
{
	printf("%d", -99 % 0);
	return 0;
}

2、对于 / 操作符如果两个操作数都为整数,执行整数除法.而只要有浮点数执行的就是浮点数除法

#include <stdio.h>
int main()
{
	printf("%d", 3/2);//打印出来的结果为1,因为是整型除法所以要用%d打印,%f打印出来为0.0000000
	return 0;
}
#include <stdio.h>
int main()
{
	printf("%f", 3.0/2);//或3/2.0或3.0/2.0,结果为1.500000,默认精度为6位
//因为是浮点数除法所以用的是%f,如果用%d打印结果为0
	return 0;
}

移位操作符:

<< 左移操作符
>> 右移操作符

 
注:移位操作符的操作数只能是整数,移动的是二进制位,符号位也会进行移动

原码反码补码

首先我们了解一个知识点

计算机中内部存储数字用的是补码

一个整数的二进制表示有3种:原码,反码,补码

我们规定正数的原反补码三码合一,都是一样的

对于负数的原反补码

假如int a = -1;int为四个字节

原码:直接根据数值写出的二进制序列
00000000000000000000000000000001
反码:原码的符号位不变,其他位按位取反
011111111111111111111111111111111110
补码:反码+1
011111111111111111111111111111111111

<< 左移操作符(移动的是补码)

左边丢弃,右边补0

#include <stdio.h>
int main()
{
    int a = 1;
	printf("%d", a << 2);
//00000000000000000000000000000001
//00000000000000000000000000000100
//左边丢失,右边补0,向右移2位,所以打印出来结果为4
	return 0;
}

>> 右移操作符(移动的是补码)

右移操作符有两种位移方式

1、算数位移

右边丢弃,左边补原符号位的数字

2、逻辑位移

右移丢失,左边补0

#include <stdio.h>
int main()
{
	int a = -1;
	printf("%d", a >> 2);
//打印出来结果还是-1
//说明在这个编译器进行的是算数位移
	return 0;
}

注:在a是有符号整型的负数时位移运算的结果因编译器而异,在许多编译器会进行逻辑运算或者算数运算,不要对负数位移,无论采用哪种方式都会降低程序的可移植性

注:a<<-5标准未定义,会产生未知结果,所以要写成a>>5

位操作符:

&   按位与        按(补码二进制)位与
|   按位或        按(补码二进制)位与
^   按位异或        按(补码二进制)位与


注:他们的操作数必须是整数

& //按位与

规则:1与1为1,1与0和0与0都为0

#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = a & b;
	printf("%d", c);//打印结果为0
	return 0;
}
//a的二进制位00000000000000000000000000000001
//b的二进制位00000000000000000000000000000010
//c的二进制位00000000000000000000000000000000

|   按位或 

规则:1与1和1与0为1,0与0为0

#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = a | b;
	printf("%d", c);//打印的结果为3
	return 0;
}
//a的二进制位00000000000000000000000000000001
//b的二进制位00000000000000000000000000000010
//c的二进制位00000000000000000000000000000011

^   按位异或  

规则:1与1和0与0为0,只有1与0为1

#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = a ^ b;
	printf("%d", c);//打印的结果是3
	return 0;
}
//a的二进制位00000000000000000000000000000001
//b的二进制位00000000000000000000000000000010
//c的二进制位00000000000000000000000000000011


赋值操作符:

=        (+=        -=        *=        /=        %=        >>=        <<=        &=        |=        ^=)复合赋值赋

赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值

int a = 1;

a=20;//将a赋值

赋值操作符可以连续使用:

int a = 10;
int x = 0;
int y = 20;
a = x = y+1;//连续赋值
//将y+1的值赋给x,再将x赋给a

不过为了方便调试我们一般把赋值拆开来写

int a = 10;
int x = 0;
int y = 20;
x = y+1;
a = x;//这样代码看着简洁很多

复合赋值符+=,其余效果差不多,不做过多介绍

int x = 10;
x = x+10;
x += 10;//使代码看着更加简洁


单目操作符:

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

!      逻辑反操作

将真(非0)变成假(0),假(0)的变成真(非0,默认为1)

#include <stdio.h>
int main()
{
	int a = !0;
	printf("%d", a);//结果为1
	return 0;
}
#include <stdio.h>
int main()
{
	int a = !1;
	printf("%d", a);//结果为0
	return 0;
}

-,+负值,正值

-1的话为负数,+1为正数,通常将正负省略

&      取地址和*      间接访问操作符(解引用操作符)

#include <stdio.h>
int main()
{
	int a = 10;
	printf("%p\n", &a);//%p打印的是地址,&a是获取a的地址,打印出来的是a的地址
	int* pa = &a;相当于int*pa; pa=&a;这里的*是指针的定义,是一个双目操作符
    //意思是定义一个int类型指针,然后用a的地址给p赋值;
	*pa = 20;//*pa的*为解引用操作符,通过*pa找到a的地址,然后将它赋值为20
	printf("%d", *pa);//打印出来为20
	return 0;
}

sizeof    操作数的类型长度(以字节为单位)

它的返回类型是无符号整型

#include <stdio.h>
int main()
{
	int a;
	printf("%d\n", sizeof a);//计算操作数的大小时候可以不用括号,打印结果为4
	printf("%d\n", sizeof(int));//计算数据类型大小时候必须要用括号,打印结果是4
	return 0;
}//这正能说明sizeof不是函数

我们再来深度了解一下sizeof操作符 

#include <stdio.h>
void test1(int arr[])
{
printf("%d\n", sizeof(arr));//结果是4或者8,因为数组传参相当于传递了数组首元素的地址
}//相当于传递了一个指针int*arr,所以是4或者8
void test2(char ch[])
{
printf("%d\n", sizeof(ch));//结果是4或者8
}
int main()
{
int arr[10] = {0};
char ch[10] = {0};
printf("%d\n", sizeof(arr));//结果是40,因为int类型为4个字节,元素为10个,所以数组大小为40
printf("%d\n", sizeof(ch));//结果是10,因为char类型为1个字节,元素为10个,所以数组大小为10
test1(arr);
test2(ch);
return 0;
}

~      对一个数的二进制按位取反(补码的二进制位)

全部位按位取反,包括符号位

#include <stdio.h>
int main()
{
	int a = 1;
	int b = ~a;
	printf("%d\n",b);//结果为-2,
    //a的补码为00000000000000000000000000000001
    //取反后b为11111111111111111111111111111110
    //得到b的原码的值为10000000000000000000000000000010
	printf("%d\n", a);//结果为1,说明取反不改变a的值
	return 0;
}

--      前置、后置--
++      前置、后置++

前置是先自加1(或者自减1)再使用,后置是先使用再自加1(或者自减1)

#include <stdio.h>
int main()
{
	int a = 1;
	int b = 1;
	printf("%d\n", ++a);//结果为2,因为前置++是先自加1再使用
	a = 1;//将a赋值为1,因为++会改变a的值
	printf("%d\n", a++);//结果为1,因为后置++是先使用后自加
	printf("%d\n", --b);//结果为0,因为前置--是先自减1再使用
	b = 1;//将a赋值为1,因为--会改变a的值
	printf("%d\n", b--);//结果为1,因为后置--是先使用手自减1
	return 0;
}

注:该操作符会改变操作数的值

(类型)    强制类型转换

#include <stdio.h>
int main()
{
	int a = 3.14;
	printf("%d\n", a);//结果为3,虽然可以进行正常编译但是会出现警告
	return 0;
}

 当我们使用int a = (int)3.14;

虽然结果还是3,但是警告会消失


关系操作符:

>        >=        <        <=        !=        ==   

比较两个操作数的大小

注:在编程时候要注意不要将==与=写反了


逻辑操作符:

&&   逻辑与
||      逻辑或

&&   逻辑与

必须操作符两边的操作数都是真,结果才是真

#include <stdio.h>
int main()
{
	printf("%d\n", 1&&0);//结果为0
	return 0;
}
#include <stdio.h>
int main()
{
	printf("%d\n", 1&&2);//结果为1
	return 0;
}

它可以控制求值顺序

#include <stdio.h>
int main()
{
  int i = 0,a=0,b=2,c =3,d=4;
  i = a++ && ++b && d++;
  printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);//打印的结果为1,2,3,4
  return 0;
}

这是因为a++&++b的时候,a已经为0了,后面的指令就没有继续执行了

||      逻辑或

只要有一边为真结果就是真,只有当两边都是假才为假

#include <stdio.h>
int main()
{
	printf("%d\n", 1||0);//结果为1
	return 0;
}
#include <stdio.h>
int main()
{
	printf("%d\n", 0||0);//结果为0
	return 0;
}

它也可以控制求值顺序

#include <stdio.h>
int main()
{
	int i = 0, a = 1, b = 2, c = 3, d = 4;
    i = a++||++b||d++;
	printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);//打印结果是2,2,3,4
	return 0;
}

当前a++||++b的时候,a++为真,后面的指令就没有执行了


条件操作符:

exp1 ? exp2 : exp3(也成为三目操作符)

当exp1为真时执行exp2,否则执行exp3

#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	printf("%d\n",a>b?a:b);//结果为2,因为a>b为假,所以执行b
	return 0;
}

逗号表达式:

exp1, exp2, exp3, …expN

逗号表达式,就是用逗号隔开的多个表达式
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果

#include <stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int c = (a += a, b += a, c = a + b);
	printf("%d\n", c);//结果为6,结果为c=a+b的结果
	return 0;
}


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

 [ ] 下标引用操作符

 ( ) 函数调用操作符

访问一个结构的成员:

.         结构体.成员名
->         结构体指针->成员名

 [ ] 下标引用操作符

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", arr[1]);//两个[]不是一个意思
	//第一个是创建数组时候的分隔符,第二个是下表引用操作符,用来通过数组的下标找到数组的元素
	//[]的操作数有两个,数组名和下标
	return 0;
}

 ( ) 函数调用操作符

接受一个或者多个操作数,第一个操作数是函数名,剩余的操作数就是传递给函数的参数

printf("%d",10);//printf为第一个操作数函数名

访问一个结构的成员:

.         结构体.成员名

#include <stdio.h>
struct person
{
	char name[20];
	int age;
	float weight;
    //name,age,weight为结构体成员名(结构体变量)
};//创建一个结构体

int main()
{
	struct person jake = { "jake",25,65.5 };//jake为结构体变量名
	printf("%s %d %.1f", jake.name, jake.age, jake.weight);
    //通过结构体变量名.结构体成员名来进行访问
    //打印出来的结果为jake 25 65.5
	return 0;
}


->         结构体指针->成员名

#include <stdio.h>
struct person
{
	char name[20];
	int age;
	float weight;
};//创建一个结构体

int main()
{
	struct person jake = { "jake",25,65.5 };
	struct person* p = &jake;//创建一个结构体指针,将结构体jake的地址存入p中
	printf("%s %d %.1f", p->name, p->age, p->weight);//p指向的对象的name,age,weight
    //打印出来的结果为jake 25 65.5
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一起慢慢变强

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

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

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

打赏作者

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

抵扣说明:

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

余额充值