您的位置:首页 > 编程语言 > C语言/C++

C语言操作符与表达式小结

H_Strong 2018-03-25 20:56 10 查看

c语言操作符和表达式小结

本篇文章主要简述c语言操作符的一些基本用法,以及一些典型的问题的辨析。

目录

c语言操作符和表达式小结
目录
算数操作符

位移操作符

位操作符
小练习题

赋值运算符

复合运算符

单目操作符

关系操作符

逻辑操作符
小练习题

条件操作符

逗号操作符
小练习题

表达式求值
小练习题

算数操作符

C语言中算数操作符包括:

+ - * / %


值得注意的是,在两个整数除法运算时, / 执行整除运算;在两个浮点数除法运算时, / 进行浮点型除法运算。在进行取模运算时, % 只接受整形数,不接受其他类型的数。

位移操作符

C语言中位移操作符包括:

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


位移操作符的作用是,讲一个数值在二进制层面上,将它的位进行向左或是向右的移动。向左移动的过程当中,最前面的几位将会被丢弃,而后面将会按照丢弃的位数进行补0。向右移动的过程当中,后面的几位将会被丢弃,前面将会补1(在正数情况下)。右移操作时,若移动的数是负数,将进行逻辑移位,前面回补1。



*使用位移运算符时,向右移动n位,相当于除以 2^n;向左移动n位,相当于乘以2^n。

*位移运算比算数运算更加高效。

*在使用位移运算符时,通常不移动负数,例如:a<<-5。因为编译器没有对这类操作有详细的定义,在使用中应该避免这样用。

位操作符

位操作符有:

按位与 &   按位或 |  按位异或 ^


位操作符的使用是按照位来运算的,拿按位异或来说,上下对其的两个位进行异或运算,相同为0,不同为1。设 a = 0110 1110, b = 0010 1011。



小练习题

给定一个整数,返回这个整数的二进制形式的1的个数。

#include<stdio.h>
#include<process.h>
int main()
{
int value = 0;
int count = 0;
scanf_s("%d", &value);
while (value != 0)
{
if (value < 0)
{
value = -value;
count = count + 1;// 负数的符号位加一
}
if ((value % 2) != 0)// 模2就相当于二进制表达剪掉一位
{
count = count + 1;
}
value = value >> 1;//向右位移一位
}
printf("这个数有%d个1\n", count);
system("pause");
return 0;
}






十进制层面:15 % 2 = 1,7 % 2 = 1, 3 % 2 = 1, 1 % 2 = 1;

二进制层面 : 1111>>1=0111,0111>>1=0011,0011>>1=0001,0001>>1=0000;

赋值运算符

赋值运算符,是将等号=右边的值储存于等号左边的值。

例如: a = b + 1;

这里需要注意的是,不建议进行连续赋值操作。虽然在语法上它是可行的,但是减弱了代码的可读性,使得调试和阅读产生了影响。

例如:r = s + ( t = u - v) / 3 可以拆成: t = u - v; r = s + t / 3;

而后者明显比前者更好理解。

复合运算符

复合运算符有如下:

+=  -=  *=  /=  %=  <<=  >>=  &=  ^=  !=


复合运算符可以减少代码的书写量,可以更好的偷懒,另外编译器也可以产生紧凑的代码。

例如: y+(x/2-10+f(z)) = y+(x/2-10+f(z)) +1; 可写成 y+(x/2-10+f(z)) += 1;

编译器算前者要调用两次f(z)函数,而后者只需要一次f(z).

单目操作符

单目操作符如下:

!  ++   -(负号)   &   sizeof  ~  --  +(正号) *(指针)  (类型)


* 这里主要说说sizeof,sizeof可以用来判断变量和类型的大小,它的单位是字节(byte)。

当它判断类型时要加括号,例:sizeof(int),判断变量时可以不加括号。

在判断表达式长度的时候,sizeof( a = b + 1);对其整体进行判断,并不对其进行计算。

*(类型)操作符被称之为强制类型转换。如(float)a,这个操作符有很高的优先级,在对表达式使用的时候要用括号括起来,以免产生错误。

* 自增运算符需要注意的问题,++i,表示先加后用, i++,表示先用后加。

#include<stdio.h>
#include<process.h>
int main()
{
int i = 0, a = 0, b = 0;
a = i++;
b = ++i;
printf("a = %d, b = %d\n", a, b);
system("pause");
return 0;
}




关系操作符

关系操作符如下:

>  >=  <  <=  !=  ==


这里需要注意的是:在进行while(),if()判断的时候,将==号错写成=号。

例如: if(x==5) 错写成 if(x=5)

以上在编译器编译的时候并不会报错,但程序的逻辑是错误的,所以建议将其写成:

if ( 5 == x) 数字在前,变量在后。

逻辑操作符

&&  ||


逻辑操作符存在一个行为:短路求值

其表述如下:&&操作符的左操作符总是首先进行求值,如果它的值为真,然后就对右操作数进行求值。如果左操作数的值为假,那么右操作数就不必求值,因为整个表达式肯定为假;同理||操作符如果做操作数为真,那么整个表达式就为真。

小练习题

这是一道非常典型的题。

#include<stdio.h>
#include<process.h>
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\n d = %d\n", a, b, c, d);
system("pause");
return 0;
}




程序执行到第二行的时候,碰到a++,这时是先用后加,所以0与右操作数,表达式为假,然后

0&&d++还是假,程序结束。根据短路求值,只有a++执行了操作,b和d都没有执行,所以结果如图所示。请读者朋友自行换掉注释来算得答案。

条件操作符

条件操作符如下:

?  :


条件操作符很特殊,它是一个三目操作符。它所表达的是 if……else的关系。

if(a>5)
c[2*b + e(d/5)] = 1;
else
c[2*b + e(d/5)] = 2;
||
c[2*b + e(d/5)] = a > 5 ? 1 : 2;


它也可以减少代码量,少打一次表达式,就少了出错的可能性。

逗号操作符

逗号操作符如下:

代码1 , 代码 2 ,……, 代码 n


逗号表达式使得编译器自左向右,依次处理代码,整个式子的表达式的值依照最后一个逗号为准。

使用逗号操作符可以做到一些骚操作,例如对于条件,和循环语句的简化。

a = f1(x);
b = f2(x + a);
for (c = f3(a, b); c > 0; c = f3(a, b))
{
a = f1(++x);
b = f2(x + a);
}
||
for (c = f3(f1(x), f2(x + a);); c > 0; c = f3(f1(++x), f2(x + a)))


小练习题

下面的程序将打印几次呢?

#include<stdio.h>
#include<process.h>
int main()
{
int i = 0, j = 0;
for (i = 0, j = 0; j = 0; i++, j++)
{
printf("hehe\n");
j++;
}
system("pause");
return 0;
}


答案是零次。因为初始条件中 i = 0 , j = 0,所以最终的判定是最后一个逗号后的表达式。for的终止条件是 j = 0。所以程序不执行。

表达式求值

1.整形提升

在表达式求值的过程中,字符型和短整型操作数在使用之前会被转换为普通的整形。

char a, b, c;
a = b
9f17
+ c;// b,c先被提升为普通整形,然后将计算结果截断,再传给a.


2.优先级顺序

下面这段话是《c和指针》里的:

两个相邻操作符的执行顺序由他们的优先级决定。如果他们的优先级相同,它们的执行顺序由它们的结合性决定。除此之外,编译器可以自由的决定热河顺序表达式进行求值,只要他不违背逗号、&&、||和条件操作符所施加的限制。

小练习题

这段代码会输出什么?

#include<stdio.h>
#include<process.h>
int fun()
{
static int count = 1;
return ++count;
}
int main()
{

int a;
a = fun() - fun()*fun();
printf("%d\n", a);
system("pause");
return 0;
}


当初我在这里想的是4 - 2 * 3 = -2;但是实际结果确是 -10。这里或许执行了 2 - 3 * 4 = - 10;

在书上说,不同编译器对函数调用的顺序是不同的,如果它们的执行具有副作用,比如一些I/O任务或是修改全局变量,那么函数顺序调用的不同可能会产生不同结果。

所以这里也可能执行了 2 - 4 * 3 = -10;

谢谢大家在百忙之中,阅读本片文章,这篇文章的大部分内容来自于《c和指针》的学习。

PS:第一个小练习题已修改,原题不能处理负数。