C语言操作符详解(上)
- 前言
- 1. 算术操作符
- 2. 移位操作符
- 2.1 左移操作符(<<)
- 2.2 右移操作符(>>)
- 3. 位操作符
- 3.1 按位与(&)
- 3.2 按位或(|)
- 3.4 按位异或(^)
- 3.5 一道变态的面试题
- 4. 关系操作符
- 5. 单目操作符
- 单目操作符介绍:
- 5.1 单目操作符(!)
- 5.2 单目操作符(~)
- 5.3 单目操作符(&、*)
- 5.4 单目操作符(++、--)
- 5.5 单目操作符(sizeof)和数组
- 6. 结尾
前言
在C语言中,C标准提供了丰富的操作符,被用来对数据进行操作和计算,常用数学计算、比较、逻辑运算等操作。操作符是编程语言中非常重要的一部分,它们可以使程序更加简洁、高效,同时也可以增强代码的可读性和可维护性。本文将详细系统介绍C语言操作符,希望能帮读者全面理解C语言操作符!
1. 算术操作符
算术操作符分为以下5种,虽然简单,但还是有一些细节需要注意。
(+)、(-)、(*)、(/)、(%)
- 除了%(取余)操作符之外,其他几个操作符可以作用于整数和浮点数。
- 对于/操作符,如果两个操作数都为整数,执行整数除法。而只要有一个浮点数就执行浮点数除法。
- %操作符的两个操作数必须为整数。返回的是整除之后的余数。
2. 移位操作符
在C语言中,移位操作符分为以下两种
- <<左移操作符
- >>右移操作符
相关知识补充:
#include <stdio.h>
int main()
{
int a = 15;
//00000000000000000000000000001111 - 原码
//00000000000000000000000000001111 - 反码
//00000000000000000000000000001111 - 补码
int b = -15;
//10000000000000000000000000001111 - 原码
//11111111111111111111111111110000 - 反码
//11111111111111111111111111110001 - 补码
return 0;
}
Tips:
- 位移操作符的操作数只能是整数。
- 计算机能处理的是二进制的信息。而整数的二进制表示形式分为三种:原码、反码、补码。
- 正整数的原码、反码、补码是相同的。负整数的反码是原码符号位不变,其他未按位取反、反码在加1就得到补码。
2.1 左移操作符(<<)
移位规则:
左边抛弃、右边补0
例子:
#include <stdio.h>
int main()
{
int a = 15;
//00000000000000000000000000001111 - (a)补码
int b = a << 1;
//对a的补码右移一位得到b的补码,左边抛弃,右边补0
//00000000000000000000000000011110 - (b)补码
//00000000000000000000000000011110 - (b)反码
//00000000000000000000000000011110 - (b)原码
printf("b=%d\n", b); //b得值为:30
return 0;
}
2.2 右移操作符(>>)
移位规则:
C语言中,右移运算分为两种:
- 逻辑右移:左边用0填充,右边丢弃。
2. 算术右移:左边用原该值的符号位填充,右边丢弃。
上述两种运算方式,C语言没有明确规定到底是算术右移还是逻辑右移。但一般编译器上采用的是算术右移。
例子:
int main()
{
int a = -15;
//10000000000000000000000000001111 - 原码
//11111111111111111111111111110000 - 反码
//11111111111111111111111111110001 - 补码
int b = a >> 1;
//左边用原该值的符号位填充,右边丢弃
//11111111111111111111111111111000 - 补码
//11111111111111111111111111110111 - 反码
//10000000000000000000000000001000 - 原码
printf("b=%d\n", b); //b的值为:-8
return 0;
}
警告:
对于移位运算符,不要移动负位数,这个行为C标准未定义的。
int num=10;
num>>-1; //error
3. 位操作符
在C语言中,位操作符有以下三种:&(按位与)、|(按位或)、^(按位异或)。
Tips:位操作符的操作数必须是整数,同时也是操作二进制位的。
3.1 按位与(&)
& — 补码对应的二进制位有0则为0,两个同时为1才是1.
例子:
int main()
{
int a = 3;
//00000000000000000000000000000011 - 补码
int b = -5;
//10000000000000000000000000000101 - 原码
//11111111111111111111111111111010 - 反码
//11111111111111111111111111111011 - 补码
int c = a & b;
//&补码对应的二进制位有0则为0,两个同时为1才是1.
//00000000000000000000000000000011 - 补码(a)
//11111111111111111111111111111011 - 补码(b)
//00000000000000000000000000000011 - 补码(c)
printf("c=%d\n", c); //c的值为:3
return 0;
}
3.2 按位或(|)
| — 补码对应的二进制位有1则为1,两个同时为0才是0.
例子:
int main()
{
int a = 3;
//00000000000000000000000000000011 - 补码
int b = -5;
//10000000000000000000000000000101 - 原码
//11111111111111111111111111111010 - 反码
//11111111111111111111111111111011 - 补码
int c = a | b;
//&补码对应的二进制位有1则w为1,两个同时为0才是0.
//00000000000000000000000000000011 - 补码(a)
//11111111111111111111111111111011 - 补码(b)
//11111111111111111111111111111011 - 补码(c)
//11111111111111111111111111111010 - 反码(c)
//10000000000000000000000000000101 - 原码(c)
printf("c=%d\n", c);//c的值为:-5
return 0;
}
3.4 按位异或(^)
|^— 补码对应的二进制位不相同则为1,两个相同则为0.
int main()
{
int a = 3;
//00000000000000000000000000000011 - 补码
int b = -5;
//10000000000000000000000000000101 - 原码
//11111111111111111111111111111010 - 反码
//11111111111111111111111111111011 - 补码
int c = a ^ b;
//^ 补码对应的二进制位不相同则为1,两个同时为1或0时才是0.
//00000000000000000000000000000011 - 补码(a)
//11111111111111111111111111111011 - 补码(b)
//11111111111111111111111111111000 - 补码(c)
//11111111111111111111111111110111 - 反码(c)
//10000000000000000000000000001000 - 原码(c)
printf("c=%d\n", c);//c的值为:-8
return 0;
}
3.5 一道变态的面试题
不能创建临时变量(第三个变量),实现两个数的交换。
int main()
{
int a = 10;
int b = 20;
//交换,按位异或是支持交换律的
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a=%d b=%d\n", a, b);
return 0;
}
- 按位异或是支持交换律的。
4. 关系操作符
这些关系运算符比较简单,没什么可介绍的。
5. 单目操作符
单目操作符介绍:
5.1 单目操作符(!)
(!)逻辑反操作,顾名思义就是把真变成假,把假变成真。
int main()
{
int flag = 0;//下面两种判断flag为0就执行语句的方法,效果一样
//方法1:
if (flag == 0)
{
//语句;
}
//方法2:flag为0,则为假。!a则为真,执行语句
if (!flag)
{
//语句;
}
return 0;
}
5.2 单目操作符(~)
单目操作符(~)是按补码二进制位全部取反.(包括符号位)
例子:
int main()
{
int a = 0;
//00000000000000000000000000000000 - 补码
int b = ~a;
//~a--对a的补码全部取反
//11111111111111111111111111111111 - 补码
//11111111111111111111111111111110 - 补码
//10000000000000000000000000000001 - 原码
printf("%d\n", b); //b的值位:-1
return 0;
}
5.3 单目操作符(&、*)
单目操作符(&、*)都运用于指针。
int main()
{
int a = 0;
//pa是指针变量
int* pa = &a; //&—取地址操作符—取出a的地址
//解引用操作符(间接访问操作符)—通过pa中存放的地址,找到指向的空间(内容)
*pa = 20;
return 0;
}
5.4 单目操作符(++、–)
单目单目操作符++(- -),分为前置++(- -)和后置++(–)
前置++(–): 先++(- -),在使用。
后置++(–): 先使用,在++(- -)。
例子1:
int main()
{
int a = 2;
int b = --a; //前置--,先--,在使用
//a=a-1,b=a
printf("a=%d b=%d\n", a, b);//a,b的值都为:1
return 0;
}
例子2:
int main()
{
int a = 2;
int b = a--; //后置--,先使用,在--
//b=a,a=a-1
printf("a=%d b=%d\n", a, b);//a的值为1,b的值为2
return 0;
}
前置++和后置++同理。
5.5 单目操作符(sizeof)和数组
单目操作符(sizrof)用于计算操作数的类型长度。(单位字节)
#include <stdio.h>
void test1(int arr[])
{
printf("%d\n", sizeof(arr));
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr));//10X4
printf("%d\n", sizeof(ch)); //10X1
test1(arr);
test2(ch);
return 0;
}
运行结果(x64环境下):
上述前两个结果毋庸置疑,但为什么后两个都是8byte呢?
上面调用函数test1()和test2(),传过去的是指针。C语言中,在64位机器上(x64),指针大小为8byte;在32位机器上(x86)上,指针大小为4byte.
6. 结尾
本篇文章到此就结束了!创作不易,如果对你有帮助,记得点赞加关注哦!感谢您的支持,同时也欢迎读者发表自己的见解!