本文是C语言操作符详解篇,可以帮助新手小白,快速了解c语言操作符的使用方法,每一个操作符都有列子和解释,做以参考学习。
加:+
减 : -
乘: *
除: /
取余:%
例题:
int main()
{
int a = 1;
int b = 2;
printf("%d",a+b);
return 0;
}
int main()
{
int a = 3;
int b = 2;
printf("%d", a - b);
return 0;
}
乘法: *
c语言中的乘法,并不是像数学那样是个 x ,而是一个小雪花(*)
例:
int main()
{
int a = 3;
int b = 2;
printf("%d", a * b);
return 0;
}
注意:c语言的除法,结果往往并不是那么顺人心意的,使用方法和数学的除法不那么一样,具体使用方法要看你操作的数据类型
例:
思考一下下面代码,a等于多少呢?
int main()
{
int a = 3 / 2;
printf("%d", a);
return 0;
}
答案:是1,为什么不是1.5呢? 有人会说 int 类型的a,输出出来的肯定是1啊,自然把那个0.5给抹掉了,那我们下面换一个类型看看是多少?
例:
int main()
{
float a = 3 / 2;
printf("%f\n", a);
return 0;
}
答案:1.000000 ,还是1,为什么不是1.5呢? 其实问题出现在 3 / 2 ,这两个数字都是整型的,你要是实在想要一个小数的出现的话可以把3或者2加个小数,比如 3/2.0.
int main()
{
float a = 3 / 2.0;
printf("%f\n", a);
return 0;
}
结论:你要是想得到一个小数,除数 或 被除数至少有一个是浮点数。
注:float类型不加f,会报警告:正确格式应该是:float a = 3 / 2.0f;
例:
int main()
{
int a = 7 % 3;
printf("%d\n", a);
return 0;
}
答案:1,因为是取余,和数学那个余数是一样的,所以是1
<< 左移操作符
>> 右移操作符
例:以下代码b输出的是什么?
int main()
{
int a = 2;
int b = a << 1;
printf("%d\n", b);
return 0;
}
答案: 4,不懂请看下面的详解:
解:
要想知道什么是4,先了解左移是移的什么?
其实上面的左移是把2的二进制位给想向左移动了一位
int a = 2;
int 类型是int,在内存占4个字节,也就是32位bit
现在我们要向左移动一个二进制位,效果如下
可以看见左边的0 溢出了 ,右边少了一个0,这个时候我们要补回来
补回来可以看见1到第三位去了,这个时候的二进制位其实是4了,最后得4,这个就是答案,如果看不出来为什么是4 请记住 8421
结论:左移操作符,左边丢弃,右边补0
例:以下代码b输出的是什么呢
int main()
{
int a = 10;
int b = a >> 1;
printf("%d\n", b);
return 0;
}
答案:5,不懂请看下面解析:
解析:先要知道a的二进制数:
向右移动一位
右边那个0溢出,我们舍弃,那我们左边应该补什么呢?
其实我们已经有2种情况:
1.算数右移
右边丢弃,左边补原符号位
2.逻辑右移
右移丢弃,左边补0
我们当前这个数是正数,大家要知道一个知识点,正数在内存中二进制位最高位是0,所以我们当前情况直接补0就可以了,4+1 等于5 所以是五,当然这个列子不直观,并不可以表达出来,它是算数右移,还是逻辑右移,所以我们来看下面的列子。
例2: 以下b是多少呢
int main()
{
int a = -1;
int b = a >> 1;
printf("%d\n", b);
return 0;
}
答案:-1,不懂情看解释。
解:
这里我们要引出一个知识点了
针对负数:
整数的二进制表示形式:其实有3种
原码: 直接根据数组写出的二进制序列就是原码
反码: 原码的符号位不变,其他位按位取反就是反码
补码: 反码加1,得到补码
针对正数:
原码,反码,补码相同
-1在内存中存放的是补码
负数的二进制最高位是1,正数二进制位最高位是0
我们可以在编译器中跑一下看看最后是大数字还是小数字,因为大数字的话最高位补0是正数,所以是逻辑右移,如果是-1那证明它最高位是补1是负数,证明是算术右移。
来看看结果:
& 按位与
| 按位或
^ 按位异或
注:他们的操作数必须是整数
1.& -按位(二进制位)与
例:思考一下这个c是什么结果
int main()
{
int a = 3;
int b = 5;
int c = a & b;
printf("%d\n", c);
return 0;
}
答案:1,不懂看下面解析
解:先看看他们两个数的二进制符号
规则:只要一个是0就是0,全1才是1,所以得出一个
最后结果是1。
2.& -按位(二进制位)或
例:思考下面代码打印出来是什么?
int main()
{
int a = 3;
int b = 5;
int c = a | b;
printf("%d\n", c);
return 0;
}
答案:7,不懂看下面解释:
所以是7。
3.& -按位(二进制位)异或
例:
int main()
{
int a = 3;
int b = 5;
int c = a ^ b;
printf("%d\n", c);
return 0;
}
答案:6,不懂看下面解析
所以是6
那么这些东西有什么用呢?
我们来看一下一个公司的面试题目
//不能创建临时变量(第三个变量),实现两个数的交换。
#include
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; }
简单的分析一下,来个其他的例子
int main()
{
int a = 3;
a ^ a;
0 ^ a;
return 0;
}
a ^ a =0;
0 ^ a =a;
相同的异或等于0
0可以反推回来 a;
例2:
赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值
int weight = 120;//体重
weight = 89;//不满意就赋值
double salary = 10000.0;
salary = 20000.0;//使用赋值操作符赋值。
赋值操作符可以连续使用,比如:
int a = 10;
int x = 0;
int y = 20; a = x = y+1;//连续赋值
这样的代码感觉怎么样?
那同样的语义,你看看:
x = y+1; a = x;
这样的写法是不是更加清晰爽朗而且易于调试。
! 逻辑反操作
- 负值
+ 正值
sizeof 操作数的类型长度(以字节为单位)
– 前置、后置–
++ 前置、后置++
(类型) 强制类型转换
int main()
{
int a = 10;
int arr[10] = {
0 };
printf("%d\n",sizeof(a)); // 一个字节的大小 输出4, 因为int 是4个字节
printf("%d\n", sizeof a); //可以省略括号 ,也证明了sizeof不是一个函数 是一个操作符
printf("%d\n",sizeof (int)); //int的括号不可以省略
printf("%d\n", sizeof(arr)); //arr有10个 ,类型是 int[10] 所以是40
printf("%d\n",sizeof(int [10]));//这个是数组的类型所以也可以
return 0;
}
来个题目:
思考下题
int main()
{
short s = 5;
int a = 10;
printf("%d\n",sizeof(s = a + 2));
printf("%d\n",s);
return 0;
}
答案:2,5 不懂看下面
解析:
(1)sizeof括号的表达式是不参与运算的
来看一个图
sizeof(s = a + 2)这个表达式只会在运行的时候开始,我们在编译的时候表达式并没有开始
2.~(二进制取反)
例子 思考下面的题b是多少:
int main()
{
int a = -1;
int b = ~a;
printf("%d\n",b);
return 0;
}
答案: 0,解析在下
解:
~ 对一个数的二进制取反
int a = -1,我们来看一下 -1的补码
可以看见补码是全1 ,取反变成全0
所以最后是0;
3.–(前置,后置)
例:
int main()
{
int a = 10;
int b = a++; //后置++,先使用,再++
printf("%d\n",a);//11
printf("%d\n",b);//10
return 0;
}
前置++
int main()
{
int a = 10;
int b = ++a; //前置++,先++,后使用
printf("%d\n",a);//11
printf("%d\n",b);//11
return 0;
}
来个例题:
后置–
int main()
{
int a = 10;
int b = a--; //在这一步 a--还是10,要先使用,就是先赋值给b ,然后在自减
printf("%d\n",a);//到这里 自减已经完成了, 所以它是9
printf("%d\n",b);//一开始就把10赋值过去了 所以b是10
return 0;
}
在来一个例:
int a =10;
printf("%d\n",a--); //先使用 a现在还是10
printf("%d\n",a); //使用完成 a在上一步已经减减 a是9
好了 ++ – 这些了解在这里,不建议大家深入去研究,没有太多好处来看下一部分.
*4. & * (&取地址、解引用)
我们都知道我们创建的变量函数,在内存中都是有自己的位置的,有位置的话,我们要找到他们进行操作是不是需要找到它的地址(&取地址),找到地址是不是要去找到它的实际的数值(*)进行操作,我们来看看下面的代码,和一个模拟代码在内存的图。
int main()
{
int a = 10;
printf("%p\n",&a);//取出a的地址
int *pa = &a ;//pa是用来存放地址的
//-- pa就是一个指针变量 类型是int *
*pa = 20 ;//解引用操作符,或者间接访问操作符
//把a改变20;
printf("%d\n",a); //20
return 0;
}
有的人有疑惑 &这个不是按位与吗?为什么变成了取地址了,其实 &是按位与,但是要当两边有 整数才是,&a这样就是取地址。
5.强制类型转换 ()
int main()
{
int a = 7.0;
return 0;
}
这样的代码会报一个警告,说类型double转换到int 数据会丢失。
因为7.0默认是double,存放到int里面去,就会报警告,想让它不报警告,可以也转换一下,看下图
这样就不会报警告了,把它强制转换变成了 int 类型的7.
=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
= 赋值
== 判断相等
字符串相等不可以使用等号来比较。
逻辑操作符只判断真假
&& 逻辑与
|| 逻辑或
思考以下代码,输出什么:
int main()
{
int a = 3;
int b = 0;
if (a&&b)
{
printf("打印我\n");
}
}
什么都没有,因为b = 0,0在c语言是false &&必须2个条件为真,才进入。
逻辑或(||)
思考以下代码,输出什么:
int main()
{
int a = 3;
int b = 0;
if (a||b)
{
printf("打印我\n");
}
}
来一个面试题,以下答案是多少呢?
#include
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++ && ++b && d++;
//i = a++||++b||d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
答案
为什么呢?
因为第一个a后置加加 ,是0 ,逻辑与,只要有一个是假 后面的表达式就不执行,所以是 1,2,3,4
逻辑或例子
#include
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
//i = a++ && ++b && d++;
i = a++||++b||d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
答案
为什么?
逻辑或 1个是0 ,另外一个是真, 那么真的后面就不要运算了.
一开始 a++ 是0,那么要后面还是要运算的 ,当到b不是0,为真时,后面的表达式就不需要运算了,所以是上面的答案
条件操作符也叫做三目操作符
a>5 ? a: b
//a大于5吗,如果大于 表达式 的值是a ,否则就是b
以最后一个表达式为结果 要从左向右依次计算
下面代码结果是什么?
int main()
{
int a = 3;
int b = 5;
int c = 0;
int d = (c = 5, a = c + 3, b = a - 4 ,c += 5);
printf("%d\n",d);
}
C=5 a=8 b=4 5=c+5 =10
所以结果是最后表达式的结果10
1.[ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
我们都知道数组下标index是从0开始的,下面代码定义了arr[10],那么下访问最后一个元素应该是arr[9]
int arr[10]={
1,2,3,4,5,6,7,8,9,10};//创建数组
printf("%d\n",arr[9]);
//[ ]的两个操作数是arr和9
2.( ) 函数调用操作符 接收一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数
#include
void test1()
{
printf("hehe\n");
}
void test2(const char *str)
{
printf("%s\n", str);
}
int main()
{
test1(); //实用()作为函数调用操作符。
test2("hello bit.");//实用()作为函数调用操作符。
return 0;
}
3.访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名
在c语言中 有许多类型,比如int float等等,但是我们要是想要定义一本书,那么那个书是什么类型呢?int吗?float吗?好像都不可行,所以C语言给了我们一个能力,自己创建一个类型,struct,看下面代码
. 点操作符
//创建了一个自定义的类型
struct book
{
//成员变量
char name[20];
char id[20];
int price;
};
int main()
{
//创建了一本书,名字叫b
//struct book 这个是类型
struct book b = {
"c语言","2010201", 55 };
printf("书名:%s\n",b.name);
printf("书号:%s\n", b.id);
printf("书价:%d\n", b.price);
return 0;
}
//创建了一个自定义的类型
struct book
{
char name[20];
char id[20];
int price;
};
int main()
{
//创建了一本书,名字叫b
//struct book 这个是类型
struct book b = {
"c语言","2010201", 55 };
struct book* pb =&b ;
//使用指针
printf("书名:%s\n",pb->name);
printf("书号:%s\n", pb->id);
printf("书价:%d\n", pb->price);
return 0;
}
好了以上就是c语言基础操作符的介绍,大家可以自己多看看,有不好的地方请大家评论区了评论出来,会重新编写,达到一个最好的效果。