C语言学习笔记--C运算符

C运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C语言内置了丰富的运算符,并提供了以下类型的运算符:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 杂项运算符
    本章将逐一介绍算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符和其他运算符。

算术运算符

下表显示了C语言支持的所有的算术运算符。假设变量A的值为10,变量B的值为20,则:

运算符描述实例
+把两个操作数相加A+B将得到30
-从第一个操作数中减去第二个操作数A-B将得到-10
*把两个操作数相乘A*B将得到200
/分子除以分母B/A将得到2
%取模运算符,整除后的余数B%A将得到0
++自增运算符,整数值增加1A++将得到11
- -自减运算符,整数值减少1A- -将得到9

实例
请看下面的实例,了解C语言中所有可用的算术运算符:

#include<stdio.h>
int main()
{
	int a=21;
	int b = 10;
    int c ;
   
   	c = a + b;
   	printf("Line 1 - c 的值是 %d\n", c );
   	c = a - b;
   	printf("Line 2 - c 的值是 %d\n", c );
   	c = a * b;
   	printf("Line 3 - c 的值是 %d\n", c );
   	c = a / b;
   	printf("Line 4 - c 的值是 %d\n", c );
   	c = a % b;
   	printf("Line 5 - c 的值是 %d\n", c );
   	c = a++;  // 赋值后再加 1 ,c 为 21,a 为 22
   	printf("Line 6 - c 的值是 %d\n", c );
   	c = a--;  // 赋值后再减 1 ,c 为 22 ,a 为 21
  	 printf("Line 7 - c 的值是 %d\n", c );
}

将上面的代码被编译和执行时,将会产生下列结果:

Line 1 - c 的值是 31
Line 2 - c 的值是 11
Line 3 - c 的值是 210
Line 4 - c 的值是 2
Line 5 - c 的值是 1
Line 6 - c 的值是 21
Line 7 - c 的值是 22

以下实例演示了a++和++a的区别:
实例

#include<stdio.h>
int main()
{
	int c;
	int a=10;
	c=a++;
	printf("先赋值后运算:\n");
   	printf("Line 1 - c 的值是 %d\n", c );
   	printf("Line 2 - a 的值是 %d\n", a );
   	a = 10;
   	c = a--; 
   	printf("Line 3 - c 的值是 %d\n", c );
   	printf("Line 4 - a 的值是 %d\n", a );
 
   	printf("先运算后赋值:\n");
   	a = 10;
   	c = ++a; 
   	printf("Line 5 - c 的值是 %d\n", c );
   	printf("Line 6 - a 的值是 %d\n", a );
   	a = 10;
   	c = --a; 
   	printf("Line 7 - c 的值是 %d\n", c );
   	printf("Line 8 - a 的值是 %d\n", a );
}

以上程序的执行输出结果为:

先赋值后运算:
Line 1 - c 的值是 10
Line 2 - a 的值是 11
Line 3 - c 的值是 10
Line 4 - a 的值是 9
先运算后赋值:
Line 5 - c 的值是 11
Line 6 - a 的值是 11
Line 7 - c 的值是 9
Line 8 - a 的值是 9

关系运算符

下表显示了C语言支持的所有关系运算符。假设变量A的值为10,变量B的值为20,则:

运算符描述实例
==检查两个操作数的值是否相等,如果相等则条件为真。(A==B)不为真
!=检查两个操作数的值是否相等,如果不相等则条件为真。(A!=B)为真
>检查左操作数的是否大于右操作数的值,如果是则条件为真。(A>B)不为真
<检查左操作数的值是否小于右操作数的值,如果是则条件为真。(A<B)为真
>=检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。(A>=B)不为真
<=检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。(A<=B)为真

实例
看下面的实例,了解C语言中所有可用的关系运算符:

#include <stdio.h>
 
int main()
{
   int a = 21;
   int b = 10;
   int c ;
 
   if( a == b )
   {
      printf("Line 1 - a 等于 b\n" );
   }
   else
   {
      printf("Line 1 - a 不等于 b\n" );
   }
   if ( a < b )
   {
      printf("Line 2 - a 小于 b\n" );
   }
   else
   {
      printf("Line 2 - a 不小于 b\n" );
   }
   if ( a > b )
   {
      printf("Line 3 - a 大于 b\n" );
   }
   else
   {
      printf("Line 3 - a 不大于 b\n" );
   }
   /* 改变 a 和 b 的值 */
   a = 5;
   b = 20;
   if ( a <= b )
   {
      printf("Line 4 - a 小于或等于 b\n" );
   }
   if ( b >= a )
   {
      printf("Line 5 - b 大于或等于 a\n" );
   }
}

当上面代码被编译和执行时,它会产生下列结果:

Line 1 - a 不等于 b
Line 2 - a 不小于 b
Line 3 - a 大于 b
Line 4 - a 小于或等于 b
Line 5 - b 大于或等于 a

逻辑运算符

下表显示了C语言支持的所有关系逻辑运算符。假设变量A的值为1,变量B的值为0,则:

运算符描述实例
&&称为逻辑与运算符。如果两个操作数都非零,则条件为真。(A&&B)为假
ll称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真(AllB)为真
称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假!(A&&B)为真

实例
看下面的实例,了解C语言中所有可用的逻辑运算符:

#include<stdio.h>
int main()
{
	int a=5;
	int b=20;
	int c;
	if(a&&b)
	{
		printf("Line1-条件为真\n");
	}
	 if ( a || b )
   	{
      	printf("Line 2 - 条件为真\n" );
   	}
   	/* 改变 a 和 b 的值 */
   	a = 0;
   	b = 10;
   if ( a && b )
   {
      printf("Line 3 - 条件为真\n" );
   }
   else
   {
      printf("Line 3 - 条件不为真\n" );
   }
   if ( !(a && b) )
   {
      printf("Line 4 - 条件为真\n" );
   }
}

当上面的代码被编译和执行时,它会产生下列结果:

Line 1 - 条件为真
Line 2 - 条件为真
Line 3 - 条件不为真
Line 4 - 条件为真

位运算符

位运算符作用于位,并逐位执行操作。&,l和^的真值表如下所示:

pqp&qplqp^q
00000
01011
11111
10011

假设如果A=60且B=13,现在以二进制格式表示,如下所示:
A=00111100
B=00001101
A&B=00001100
AlB=00111101
A^B=00110001
~A=11000011
下表显示了C语言支持的位运算符。假设变量A的值为60,变量B的值为13,则

运算符描述实例
&按位与操作,按二进制位进行“与”运算。运算规则:0&0=0;0&1=0;1&0=0;1&1=1;(A&B)将得到12,即为00001100
l按位或运算符,按二进制位进行“或”运算。运算规则:0|0=0;0|1=1;1|0=1;1|1=1;(A
^异或运算符,按二进制位进行“异或”运算。运算规则:0^0=0;0^1=1;1^0=1;1^1=0;(A ^ B) 将得到 49,即为 0011 0001
~取反运算符,按二进制位进行“取反”运算。运算规则:~1=0;~0=1;(~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。
<<二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。A << 2 将得到 240,即为 1111 0000
>>二进制右移运算符。将一个数的各二进制位全部右移若干位,整数左补0,负数左补1,右边丢弃A>>2将得到15,即为00001111

实例
看下面的实例,了解C语言所有可用的位运算符:

#include<stdio.h>
int main()
{
   unsigned int a=60;		/* 60 = 0011 1100 */  
   unsigned int b = 13;    /* 13 = 0000 1101 */
   int c = 0;           
 
   c = a & b;       /* 12 = 0000 1100 */ 
   printf("Line 1 - c 的值是 %d\n", c );
 
   c = a | b;       /* 61 = 0011 1101 */
   printf("Line 2 - c 的值是 %d\n", c );
 
   c = a ^ b;       /* 49 = 0011 0001 */
   printf("Line 3 - c 的值是 %d\n", c );
 
   c = ~a;          /*-61 = 1100 0011 */
   printf("Line 4 - c 的值是 %d\n", c );
 
   c = a << 2;     /* 240 = 1111 0000 */
   printf("Line 5 - c 的值是 %d\n", c );
 
   c = a >> 2;     /* 15 = 0000 1111 */
   printf("Line 6 - c 的值是 %d\n", c );
}

当上面的代码被编译和执行时,它会产生下列结果:

Line 1 - c 的值是 12
Line 2 - c 的值是 61
Line 3 - c 的值是 49
Line 4 - c 的值是 -61
Line 5 - c 的值是 240
Line 6 - c 的值是 15

赋值运算符

下表列出了C语言支持的赋值运算符:

运算符描述实例
=简单的赋值运算符,把右边操作数的值赋给左边操作数C=A+B将把A+B的值赋给C
+=加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数C+=A相当于C=C+A
- =减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数C-=A相当于C=C-A
*=乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数C*=A相当于C=C*A
/=除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数C/=A相当于C=C/A
%=求模且赋值运算符,求两个操作数的模赋值给左边操作数C%=A相当于C=C%A
<<=左移且赋值运算符C<<=2等同于C=C<<2
>>=右移且赋值运算符C>>=2等同于C=C>>2
&=按位与且赋值运算符C&=2等同于C=C&2
^=按位异或且赋值运算符C^ =2等同于C=C^2
l=按位或且赋值运算符Cl=2等同于C=Cl2

看下面实例,了解C语言中所有可用的赋值运算符:
实例

#include <stdio.h>
 
main()
{
   int a = 21;
   int c ;
 
   c =  a;
   printf("Line 1 - =  运算符实例,c 的值 = %d\n", c );
 
   c +=  a;
   printf("Line 2 - += 运算符实例,c 的值 = %d\n", c );
 
   c -=  a;
   printf("Line 3 - -= 运算符实例,c 的值 = %d\n", c );
 
   c *=  a;
   printf("Line 4 - *= 运算符实例,c 的值 = %d\n", c );
 
   c /=  a;
   printf("Line 5 - /= 运算符实例,c 的值 = %d\n", c );
 
   c  = 200;
   c %=  a;
   printf("Line 6 - %= 运算符实例,c 的值 = %d\n", c );
 
   c <<=  2;
   printf("Line 7 - <<= 运算符实例,c 的值 = %d\n", c );
 
   c >>=  2;
   printf("Line 8 - >>= 运算符实例,c 的值 = %d\n", c );
 
   c &=  2;
   printf("Line 9 - &= 运算符实例,c 的值 = %d\n", c );
 
   c ^=  2;
   printf("Line 10 - ^= 运算符实例,c 的值 = %d\n", c );
 
   c |=  2;
   printf("Line 11 - |= 运算符实例,c 的值 = %d\n", c );
 
}

当上面的代码被编译和执行时,会产生下列结果:

Line 1 - =  运算符实例,c 的值 = 21
Line 2 - += 运算符实例,c 的值 = 42
Line 3 - -= 运算符实例,c 的值 = 21
Line 4 - *= 运算符实例,c 的值 = 441
Line 5 - /= 运算符实例,c 的值 = 21
Line 6 - %= 运算符实例,c 的值 = 11
Line 7 - <<= 运算符实例,c 的值 = 44
Line 8 - >>= 运算符实例,c 的值 = 11
Line 9 - &= 运算符实例,c 的值 = 2
Line 10 - ^= 运算符实例,c 的值 = 0
Line 11 - |= 运算符实例,c 的值 = 2

杂项运算符 sizeof&三元

下表列出了C语言支持的其他一些重要的运算符,包括sizeof?:

运算符描述实例
sizeof()返回变量的大小。sizeof(a)将返回4,其中a是整数
&返回变量的地址。&a;将给出变量的实际地址。
*指向一个变量。*a;将指向一个变量。
?:条件表达式如果条件为真 ?则值为X:否则值为Y

请看下面的实例,了解C语言中所有可用的杂项运算符:
实例

#include <stdio.h>
 
int main()
{
   int a = 4;
   short b;
   double c;
   int* ptr;
 
   /* sizeof 运算符实例 */
   printf("Line 1 - 变量 a 的大小 = %lu\n", sizeof(a) );
   printf("Line 2 - 变量 b 的大小 = %lu\n", sizeof(b) );
   printf("Line 3 - 变量 c 的大小 = %lu\n", sizeof(c) );
 
   /* & 和 * 运算符实例 */
   ptr = &a;    /* 'ptr' 现在包含 'a' 的地址 */
   printf("a 的值是 %d\n", a);
   printf("*ptr 是 %d\n", *ptr);
 
   /* 三元运算符实例 */
   a = 10;
   b = (a == 1) ? 20: 30;
   printf( "b 的值是 %d\n", b );
 
   b = (a == 10) ? 20: 30;
   printf( "b 的值是 %d\n", b );
}

当上面的代码被编译和执行时,它会产生下列结果:

Line 1 - 变量 a 的大小 = 4
Line 2 - 变量 b 的大小 = 2
Line 3 - 变量 c 的大小 = 8
a 的值是 4
*ptr 是 4
b 的值是 30
b 的值是 20

C中的运算符优先级

运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。
例如x=7+3 * 2,在这里,x被赋值为13,而不是20,因为运算符 * 具有比+更高的优先级,所以首先计算乘法3*2,然后再加上7.
下表将按运算符优先级从高到低列出各个运算符,具有较高优先级的运算符出现在表格的上面,具有较低优先级的运算符出现在表格的下面。在表达式中,较高优先级的运算符会优先被计算。

类别运算符结合性
后缀() [] -> . ++ –从左到右
一元+ - ! ~ ++ – (type)*& sizeof从右到左
乘除* / %从左到右
加减+ -从左到右
移位<< >>从左到右
关系< <= > >=从左到右
相等== !=从左到右
位与 AND&从左到右
位异或 XOR^从左到右
位或 ORl从左到右
逻辑与 AND&&从左到右
逻辑或 ORll从左到右
条件?:从右到左
赋值= += -= *= /= %= >>= <<= &= ^= l=从右到左
逗号,从左到右

请看下面的实例,了解C语言中运算符的优先级:
实例

#include <stdio.h>
 
main()
{
   int a = 20;
   int b = 10;
   int c = 15;
   int d = 5;
   int e;
 
   e = (a + b) * c / d;      // ( 30 * 15 ) / 5
   printf("(a + b) * c / d 的值是 %d\n",  e );
 
   e = ((a + b) * c) / d;    // (30 * 15 ) / 5
   printf("((a + b) * c) / d 的值是 %d\n" ,  e );
 
   e = (a + b) * (c / d);   // (30) * (15/5)
   printf("(a + b) * (c / d) 的值是 %d\n",  e );
 
   e = a + (b * c) / d;     //  20 + (150/5)
   printf("a + (b * c) / d 的值是 %d\n" ,  e );
  
   return 0;
}

当上面代码被编译和执行时,会产生下面的结果:

(a + b) * c / d 的值是 90
((a + b) * c) / d 的值是 90
(a + b) * (c / d) 的值是 90
a + (b * c) / d 的值是 50

综合总结

1、利用异或 ^ 来交换两个数的值,而且不引入其他变量。

unsigned int a=60;  //0011 1100
unsigned int b=13;  //0000 1101
a=a^b;              //a=a^b=0011 0001
b=a^b;              //b=a^b=0011 1100  相当于b1=(a^b)^b
a=a^b;              //a=a^b=0000 1101  相当于a1=(a^b)^((a^b)^b)

实例

#include<stdio.h>

int main( )
{
    unsigned int a=60;         //0011 1100
    unsigned int b=13;         //0000 1101
    printf("a=%d,b=%d",a,b);   //输出a,b的值
    printf("\n");
    a=a^b;                     //a=a^b=0011 0001
    b=a^b;                     //b=a^b=0011 1100
    a=a^b;                     //a=a^b=0000 1101
    printf("a=%d,b=%d",a,b);   //输出a,b的值
}

上面代码编译和执行时,会产生下面的结果:

a=60,b=13;
a=13,b=60;

2、利用位与 &运算,判断一个整数是否是2的整数次幂。
二进制数的位权是以2为底的幂,如果一个整数 m 是 2 的 n 次幂,那么转换为二进制之后只有最高位为 1,其余位置为 0,再观察 m-1 转换为二进制后的形式以及 m&(m-1) 的结果,例如:

2 --> 0000 0010        1 --> 0000 0001        2&1 --> 0000 0010 & 0000 0001 = 0
4 --> 0000 0100        3 --> 0000 0011        4&3 --> 0000 0100 & 0000 0011 = 0
8 --> 0000 1000        7 --> 0000 0111        8&7 --> 0000 1000 & 0000 0111 = 0

可以看出所有的 1 完美的错过了,根据位与的特点可知 m&(m-1) 的结果为 0。
如果整数 m 不是 2 的 n 次幂,结果会怎样呢?例如 m=9 时:

9 --> 0000 1001        8 --> 0000 1000        9&8 --> 0000 1001 & 0000 1000 != 0

利用这一特点,即可判断一个整数是否是2的整数次幂。
示例:

int func(int num)
{
    return ((num > 0) && ((num & (num - 1)) == 0));//2的n次幂大于0
}

返回值为 1,则输入的正整数为 2 的整数次幂,返回值为 0 则不是。
对于2的幂指数的代码为:

#include <stdio.h>

int num;
int func(int num)
{
    if ((num>0)&&(num&(num-1))==0)
    {
        printf("%d是2的整数次幂",num);
    }
    else
    {
        printf("%d不是2的整数次幂",num);
    }
    return((num>0)&&(num&(num-1))==0);
}

int main()
{
    printf("请输入要查询的数\n");
    scanf("%d",&num);
    func(num);
}

3、对取余运算的说明
取余,也就是求余数,使用的运算符是 %。C 语言中的取余运算只能针对整数,也就是说,% 的两边都必须是整数,不能出现小数,否则编译器会报错。
另外,余数可以是正数也可以是负数,由 % 左边的整数决定:

  • 如果 % 左边是正数,那么余数也是正数;
  • 如果 % 左边是负数,那么余数也是负数;
    例如:
#include <stdio.h>

int main()
{
    printf( "100%%12=%d \n100%%-12=%d \n-100%%12=%d \n-100%%-12=%d \n", 100%12, 100%-12, -100%12, -100%-12 );
    return 0;
}

运行结果:

100%12=4
100%-12=4
-100%12=-4
-100%-12=-4 

4、a++ 与 ++a 区别在于一个后加,一个先加。
a++ 输出 a 的值再自加,缓存 a 自加后的结果,用于下次进行与 a 相关的计算。
++a 则相当于 a+1。

#include <stdio.h>

int main(int argc, char **argv) {
    int a=100;
    int b=50;
//    b++;
    printf("%d,%d\n",a++,++a);
    printf("%d,%d",b++,++b);
    return 0;
}

运行后输出:

101,102
51,52

若不注释 b++:

int main(int argc, char **argv) {
    int a=100;
    int b=50;
    b++;
    printf("%d,%d\n",a++,++a);
    printf("%d,%d",b++,++b);
    return 0;
}

则结果为:

101,102
52,53
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值