文章目录
前言
c语言当中有着大量的操作符,本篇文章相较于之前的【初识c语言】中的所讲的操作符做出了对各个操作符的具体内容更加深入的探究。类似 - + = 这种比较简单的这篇文章就不再过多解释了
一、算术操作符(+ - * / %)
除法“ / ”的结果返回的是商;取模“ % ”运算返回的是余数
需要注意的是除法( / ),当 9/2 时,按道理结果应该是 4.5
int main()
{
int i = 9 / 2;
printf("%d\n", i);
return 0;
}
但是实际上输出结果为 4 ,因为 9 和 2 都是int型,所以输出值也是整形,如果要得到小数该怎么做呢 ?
int main()
{
double i = 9.0 / 2;
//int i = 9 /2.0;
printf("%lf\n", i);
return 0;
}
只要除法两边有一个是 x.0 的形式,结果就是小数型,注意定义和输出的时候类型也
应该用浮点型
二、移位操作符(<< >>)
1. <<左移操作符
左移操作符:
a 的真值为 2,2的二进制序列为 0000 0010(为了方便这里只用八位),左移操作符就是将二进制序列向左移动一位,变成 0000 0100 ,其真值为 4 再左移一次就成了 0000 1000,真值为 8 ,所以,左移操作符的意义就是左移几位,就将变量扩大几倍
int main()
{
int a = 2;//0000 0010
a = a << 1;//0000 0100
printf("%d\n", a);
return 0;
}//结果为 4
2. >>右移操作符
右移操作符就和左移操作符逻辑完全一样了,右移几位,缩小几倍
算数右移:右移时高位复制符号位
逻辑右移:右移时高位直接补零
int main()
{
int a = -1;//1111 1111
a = a >> 1;//1111 1111
printf("%d\n", a);
return 0;
}//结果为 -1
三、位操作符(& | ^)
※三个操作符的操作数必须为整数
1. & 按位与
同为真 “1” 时 结果为真 “1”
int i = 3;
int j = 5;
printf("%i\n", i & j);// i、j按位与
//0000 0011
//0000 0101
//0000 0001 结果
2. | 按位或
同时为假 “0” 结果为假 “0”
int i = 3;
int j = 5;
printf("%i\n", i & j);// i、j按位与
//0000 0011
//0000 0101
//0000 0111 结果
3. ^ 按位异或
相同则结果为假 “0”
小细节:两次异或可以抵消(a == a ^ b ^ b)
int i = 3;
int j = 5;
printf("%i\n", i & j);// i、j按位与
//0000 0011
//0000 0101
//0000 0110 结果
小练习:交换两个数 a b的值,要求不使用第三个变量
//方法一:
int a = 3;
int b = 5;
a = a + b;//a = 8
b = a - b;//b = 3
a = a - b;//a = 5
//方法二:
int a = 3;
int b = 5;
a = a ^ b;//0000 0110
b = a ^ b;//0000 0011
a = a ^ b;//0000 0101
作业:编写一个代码实现:求一个整数存储在内存中的二进制中 1 的个数
分析:例如求0000 0111中1 的个数,我们可以运用上面的知识想到,如果给它按位与 1 ,结果刚好是 1 ,因为
0000 0111
0000 0001同时为1 结果为1 .
如果结果是1,那么久计数器+1,如果不是1,那么让被比较的数右移移位继续比较 1。
代码实现: 这里注意循环右移时,while语句的表达式应为 被比较的数 ,等到右移至零,表达式为假刚好跳出循环
int main()
{
int a = 7;//0000 0111
int count = 0;
while (a)
{
if (a & 1 ==1)
{
count++;
}
a = a >> 1;
}
printf("%d\n", count);
return 0;
}//结果为 3 .
四、赋值操作符( = += -= *= /= %= <<= >>=)
赋值操作符可以连续使用(连续赋值)
int a = 10;
int b = 0;
int c = 20;
a = b = c + 1;//a = b = 21____a = 21
int a = 20;
a = a + 10;
a += 20;//与上面一行意思是一样的
五、单目操作符(! - + & sizeof ~ ++ – (类型))
1. sizeof 计算类型所占空间
单位是字节 B
int a = 10;
char arr[10] = { 0 };
printf("%d\n", sizeof(arr));// 10
printf("%d\n", sizeof(arr[0]));//1
printf("%d\n", sizeof a);//4
练习:
short s = 5;//2字节
int a = 10;//4字节
printf("%d\n",sizeof(s = a + 2));//2 由s决定大小,已经在程序编译期间确定
printf("%d\n", s);//5
sizeof 括号内放的表达式不参与运算!
注意:sizeof计算数组传参问题
我们知道,在数组传参时,传过去的仅仅是数组首元素的地址,既然是地址那么就分为32位或者64位,转为字节单位就是4字节或者8字节,所sizeof计算传参后的数组大小要么是4要么是8
void test1(int* arr)
{
printf("%d\n", sizeof(arr));//4/8
}
void test2(char* ar)
{
printf("%d\n", sizeof(ar));//4/8
}
int main()
{
int arr[10] = { 0 };
char ar[10] = { 0 };
printf("%d\n", sizeof(arr));//40
printf("%d\n", sizeof(ar));//10
test1(arr);
test2(ar);
return 0;
return 0;
}
2. ~ 对一个数的二进制位按位取反
int a = -1;
a = ~a;
//1111 1111 1111 1111(-1 的补码)
//按位取反:0000 0000 0000 0000
printf("%d\n", a);//结果为 0
3.前置、后置-- ++
前置:先运算,再使用;
后置:先使用,再运算。
int a = 10;
int b = 3;
printf("%d\n", ++a);//11 a = 11
printf("%d\n", b--);//3 b = 2
4. * 解引用操作符 & 取地址操作符
int a = 10;
&a;//通过&取出a的地址
printf("%p\n", &a);//000000DA6BAFFA84
如果将这个地址存放在一个空间里的话,如:pa,此时,pa就是指针变量,记作 * pa ,此外a为int型,所以指针变量 * pa也应该为int型:
int a = 10;
int* pa = &a;//指针变量*
*pa = 20;//解引用操作符*
printf("%d\n",a);//20
5. (类型)强制类型转换
int a = (int)3.14;
printf("%d\n", a);//3
六、关系操作符(> < <= >= != ==)
用于判断大小、测试不相等或相等
判断两个字符串是否相等不能用 == ;
应该使用strcmp函数
strcmp(str_1,str_2); //字符串匹配,返回零说明匹配成功
七、逻辑操作符(&& || )
区分按位与 & 按位或 |
逻辑与&&:只有操作数同时满足才为真
int a = 10;
int b = 3;
if (a > 10 && b < 5)只有当两边同时满足,结果才为真
{
printf("hehe\n");
}//hehe
逻辑或 | | :操作数只要满足其一即可返回真
int a = 10;
int b = 3;
if (a > 10 || b < 5)只有当两边同时满足,结果才为真
{
printf("hehe\n");
}//hehe
练习:代码运行结果?
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d);// 1 2 3 4
对于&&,int c = a && b;当a已经为假,那么b就不重要了,直接返回假,所以上面的代码只执行了a++。
对于 | | ,int c = a | | b; 当a为真,则直接返回真,后续无需执行,只需要执行a。
八、条件操作符(三目操作符)
1. exp1 ? exp2 : exp3
int a = 3;
int b = 0;
int c = a > 5 ? 1 : -1;
//a > 5 吗?如果大于,返回1,如果不大于,返回-1
2. 逗号表达式
从左向右依次计算,但是整个表达式的结果是最后一个表达式的结果。
int a = 3;
int b = 5;
int c = 0;
int d = (c = 5, a = c + 3, b = a - 4, c += b);
// 5 a = 8 b = 4 c = 9
printf("%d\n", d);//9
九、下标引用操作符([ ])
其作用就是通过下标访问数组元素,使用方法如下:
一个数组名 + 一个索引值
arr[ 3 ]
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", arr[4]);//[]访问数组下标为4的元素,数组默认从零开始,结果为5
return 0;
}
十、函数调用操作符(())
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10;
int b = 20;
int ret = Add(a, b);//这个( )符号就是函数调用操作符
return 0;
}
()函数用操作符接受一个或者多个操作数,第一个操作数是函数名,剩余的操作数就是传递函数的参数。
如:
test()
Add(a,b)
十一、结构成员访问操作符
在生活中需要描述一个整体的特征往往是复杂的,这时候就不能局限于c语言中固定的数据类型,因此结构体类型由此诞生,它的作用就是用来描述复杂对象的。在结构体中有多个不同的特征,而所谓结构成员访问,实际上就是对于结构体内复杂元素的访问。
例如,当我们要创建一本书的时候,可以从 书名、书号、定价出发创立一个结构体
struct Book
{
char name[20];
char id[20];
float price;
};
这样看起来,定义结构体就相当于是定义了一本什么都没有的 “ 书 ” ,它只是拥有了 “ 书 ” 的全部特征,而这些特征就需要后面人为的改变他(赋值)去创造出不同的书。
例如
int main()
{
struct Book shu1 = { "c语言","235446365",12.6};
printf("书名:%s\n", shu1.name);
printf("书号:%s\n", shu1.id );
printf("定价:%f\n", shu1.price );
return 0;
}
第一种写法:
对于上述代码要注意的是使用结构体就相当于使用int char一样,需要加上变量名。 访问结构体运用的是:点操作符(结构体名 . 成员名)
第二种写法:
当拿到的是结构体的地址而不是结构体本身时,使用 -> 来访问结构体元素(结构体指针名 -> 成员名)
int main()
{
struct Book shu1 = { "c语言","235446365",12.6};
struct Book* pb = &shu1;
printf("书名:%s\n", pb->name);
printf("书号:%s\n", pb->id );
printf("定价:%f\n", pb->price);
return 0;
}
总结
本片文章基本上涵盖了c语言中常用的操作符,希望本篇能对c语言初学者在对于操作符这块能有所帮助。如有纰漏,欢迎批评指正
如果觉得这篇文章写的不错的话,可以点赞 + 收藏 + 评论支持!