vlambda博客
学习文章列表

c++ c语言 - 运算符和类型转换

c 语法5 - 运算符和类型转换

一、算术运算符

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

1、加减乘除

和一般的加减乘除无区别,注意输出格式即可,无法除以0

除法运算后得到的结果给整型变量时候,取整数部分

#include <stdio.h>

int main(void){
 int a = 10;
 int b = 20;
 
 printf("a + b = %d\n",a+b);
 printf("a - b = %d\n",a-b);
 printf("a * b = %d\n",a*b);
 printf("b / a = %d\n",b/a);
 return 0;
}

2、取余

%就是取余数运算,也就是模运算(mod)。设a,b是两个整数,a%b的结果就就是a÷b得到的余数 例如5%3=2 (商1余2) 9%4=1 (商2余1) 3%7=3 (商0余3)

#include <stdio.h>

int main(void){
 int a = 10;
 int b = 8;
 printf("a = %d\n",a);
 printf("b = %d\n",b);
 printf("a %s b = %d\n","%",a%b);
 return 0;
}

c++ c语言 - 运算符和类型转换

3、(++)与(- -)

++ 与- -是一对让算数运算方便的自增属性的算术式。

++是自增,分为前缀自增与后缀自增。而- -则是自减,也分为前缀自减与后缀自减。

但是都是等效于

i ++ / ++i ==》 i = i+1

独立式子中,没有区别,但是在与其他表达式结合的时候将发挥作用。

#include <stdio.h>

int main(void){
 int a = 10;
 printf("a++\n");
 printf("a = %d\n",a++);
 printf("a = %d\n",a);
 printf("++a\n");
 printf("a = %d\n",++a);
 printf("a = %d\n",a);
 return 0;
}

c++ c语言 - 运算符和类型转换

明显可以看出,++a与a++的区别。

二、赋值运算符

赋值运算符代表了在运算结束之后,给予变量一个值。

这里仅展示非位运算的运算符

运算符 描述 实例
= 简单的赋值运算符,把右边操作数的值赋给左边操作数 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
|= 按位或且斌值运算符 C|=2等同于C=C|2
#include <stdio.h>
int pf(int a,int c){
 printf("a = %d,c = %d\n\n",a,c);
 return 0;
}
int main(void){
   int a = 21;
   int c ;
   printf("Line 1 : =  运算符实例");c =  a;pf(a,c);
   printf("Line 2 : += 运算符实例");c +=  a;pf(a,c);
   printf("Line 3 : -= 运算符实例");c -=  a;pf(a,c);
   printf("Line 4 :*= 运算符实例"); c *=  a;pf(a,c);
   printf("Line 5 : /= 运算符实例"); c /=  a;pf(a,c);
   
   c  = 200;
   printf("Line 6 : %= 运算符实例,c 的原本值 = %d\n", c );c %=  a;pf(a,c);
   printf("Line 7 : <<= 运算符实例,c 的原本值 = %d\n", c );c <<=  2;pf(a,c);
   printf("Line 8 : >>= 运算符实例,c 的原本值 = %d\n", c ); c >>=  2;pf(a,c);
   printf("Line 9 : &= 运算符实例,c 的原本值 = %d\n", c );c &=  2;pf(a,c);
   printf("Line 10 : ^= 运算符实例,c 的原本值 = %d\n", c );c ^=  2;pf(a,c);
   printf("Line 11 : |= 运算符实例,c 的原本值 = %d\n", c );c |=  2;pf(a,c);
}

c++ c语言 - 运算符和类型转换

三、比较(关系)运算符

运算符 含  义 数学中的表示
< 小于 <
<= 小于或等于
> 大于 >
>= 大于或等于
== 判等于 =
!= 不等于

关系运算符都是双目运算符,其结合性均为左结合。关系运算符的优先级低于算术运算符,高于赋值运算符。在六个关系运算符中,<、<=、>、>=的优先级相同,高于==和!=,==和!=的优先级相同。

#include <stdio.h>
int main(){
    char c='k';
    int i=1, j=2, k=3;
    float x=3e+5, y=0.85;
    int result_1 = 'a'+5<c, result_2 = x-5.25<=x+y;
    printf"%d, %d\n", result_1, -i-2*j>=k+1 );
    printf"%d, %d\n"1<j<5, result_2 );
    printf"%d, %d\n", i+j+k==-2*j, k==j==i+5 );
    return 0;
}

c++ c语言 - 运算符和类型转换

四、逻辑运算符

一般把0为假,非0为真。计算机里的话则是1一般代表计算机输出的真值

运算符 术语 实例 结果
非(非真为假,非假为真) !a 如果a为假,则!a为真;   如果a为真,则!a为假。
&& 与(同真为真,有假为假) a&&b 如果a和b都为真,则结果为真,否则为假。
|| 或(有真为真,同假为假) a||b 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。

逻辑符非

c#include <stdio.h>

int main(void){
 int a = 10;
 int b = 0;
 printf("a = %d !a = %d\n",a, !a);
 printf("b = %d !b = %d\n",b, !b);
 return 0;
}

c++ c语言 - 运算符和类型转换

我们可以看到,当a = 10时,!a由于取反,则变成了代表假的0

当b  = 0时,则!b取反则变成了代表真的1

一般情况下,只要是非0即可代表真。

逻辑符与

#include <stdio.h>

int main(void){
 int a = 10;
 int b = 0;
 printf("a = %d,b = %d a&&b = %d\n",a, b, a&&b);
 return 0;
}

c++ c语言 - 运算符和类型转换

由于a=10代表真,b=0代表假,则a&&b代表假

逻辑符或

#include <stdio.h>

int main(void){
 int a = 10;
 int b = 0;
 printf("a = %d !a = %d\n",a, !a);
 printf("b = %d !b = %d\n",b, !b);
 printf("a = %d,b = %d a&&b = %d\n",a, b, a&&b);
 printf("a = %d,b = %d a||b = %d\n",a, b, a||b);
 return 0;
}

c++ c语言 - 运算符和类型转换

五、位运算符

真值表

p q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

假设变量 A 的值为 60,变量 B 的值为 13,则:

与运算符&

按位与操作,按二进制位进行"与"运算。运算规则:

0&0=0;   
0&1=0;    
1&0=0;     
1&1=1;

(A & B) 将得到 12,即为 0000 1100

或运算符 |

按位或运算符,按二进制位进行"或"运算。运算规则:

0|0=0;   
0|1=1;   
1|0=1;    
1|1=1;

(A | B) 将得到 61,即为 0011 1101

异或运算符^

异或运算符,按二进制位进行"异或"运算。运算规则:

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,即为 0000 1111

#include <stdio.h>

int main(void){
   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 );
}

c++ c语言 - 运算符和类型转换

六、三目运算符和逗号运算符

三目运算符 ?:

表达式1 ? 表达式2**:** 表达式3

表达式1为一个判别表达式:若表达式1为真,则整个三目运算取值表达式2

若表达式1为假,则整个三目运算取值为表达式3

#include<stdio.h>

int main(void){
 int a = 40;
 int b = 50;
 printf("%s",a>b ? "a>b" : "a<b" );
 return 0;
}

c++ c语言 - 运算符和类型转换

逗号运算符

一般用于连接定义或者声明变量以及连接表达式的运算符。逗号运算符可以结合形成逗号表达式,通过运算之后获取的话会获取到最后一位。

#include<stdio.h>

int main(void){
 int a = 40, b = 20, c = 10;    //同时定义三个整型变量
 int x = (a = 4, b = 2, c = 1); //逗号运算符表达式,x获得表达式最后一个值的结果,同时值被改写
 
 printf("X = %d\n", x);
 printf("a = %d\n", a);
 printf("b = %d\n", b);
 printf("c = %d\n", c);
 
 return 0;
}

c++ c语言 - 运算符和类型转换

七、运算符优先级

单目运算符:代表运算过程只有一个变量

双目运算符:代表运算过程存在两个变量

以此类推

同一优先级的运算符,运算次序由结合方向所决定。

简单记就是:!> 算术运算符 > 关系运算符 > && > || > 赋值运算符

优先级1

运算符 名称或含义 使用形式 结合方向 说明
[] 数组下标 数组名[常量表达式] 左到右
() 圆括号 (表达式)/函数名(形参表) 左到右
. 成员选择(对象) 对象.成员名 左到右
-> 成员选择(指针) 对象指针->成员名 左到右
-- 后置自减运算符 --变量名 左到右 单目运算符
++ 后置自增运算符 ++变量名 左到右 单目运算符

优先级2

运算符 名称或含义 使用形式 结合方向 说明
- 负号运算符 -表达式 右到左 单目运算符
(类型) 强制类型转换 (数据类型)表达式 右到左
++ 前置自增运算符 变量名++ 右到左 单目运算符
-- 前置自减运算符 变量名-- 右到左 单目运算符
* 取值运算符 *指针变量 右到左 单目运算符
& 取地址运算符 &变量名 右到左 单目运算符
! 逻辑非运算符 !表达式 右到左 单目运算符
~ 按位取反运算符 ~表达式 右到左 单目运算符
sizeof 长度运算符 sizeof(表达式) 右到左

优先级3

运算符 名称或含义 使用形式 结合方向 说明
/ 表达式/表达式 左到右 双目运算符
* 表达式*表达式 左到右 双目运算符
% 余数(取模) 整型表达式/整型表达式 左到右 双目运算符

优先级4

运算符 名称或含义 使用形式 结合方向 说明
+ 表达式+表达式 左到右 双目运算符
- 表达式-表达式 左到右 双目运算符

优先级5

运算符 名称或含义 使用形式 结合方向 说明
<< 左移 变量<<表达式 左到右 双目运算符
>> 右移 变量>>表达式 左到右 双目运算符

优先级6

运算符 名称或含义 使用形式 结合方向 说明
> 大于 表达式>表达式 左到右 双目运算符
>= 大于等于 表达式>=表达式 左到右 双目运算符
< 小于 表达式<表达式 左到右 双目运算符
<= 小于等于 表达式<=表达式 左到右 双目运算符

优先级7

运算符 名称或含义 使用形式 结合方向 说明
== 等于 表达式==表达式 左到右 双目运算符
!= 不等于 表达式!= 表达式 左到右 双目运算符

优先级8~13

优先级 运算符 名称或含义 使用形式 结合方向 说明
8 & 按位与 表达式&表达式 左到右 双目运算符
9 ^ 按位异或 表达式^表达式 左到右 双目运算符
10 | 按位或 表达式|表达式 左到右 双目运算符
11 && 逻辑与 表达式&&表达式 左到右 双目运算符
12 || 逻辑或 表达式||表达式 左到右 双目运算符
13 ? : 条件运算符 表达式1? 表达式2: 表达式3 右到左 三目运算符

优先级14

运算符 名称或含义 使用形式 结合方向
= 赋值运算符 变量=表达式 右到左
/= 除后赋值 变量/=表达式 右到左
*= 乘后赋值 变量*=表达式 右到左
%= 取模后赋值 变量%=表达式 右到左
+= 加后赋值 变量+=表达式 右到左
-= 减后赋值 变量-=表达式 右到左
<<= 左移后赋值 变量<<=表达式 右到左
>>= 右移后赋值 变量>>=表达式 右到左
&= 按位与后赋值 变量&=表达式 右到左
^= 按位异或后赋值 变量^=表达式 右到左
|= 按位或后赋值 变量|=表达式 右到左

优先级15

运算符 名称或含义 使用形式 结合方向 说明
, 逗号运算符 表达式,表达式,… 左到右 从左向右顺序运算

类型转换

数据拥有不同的数据类型,不同数据类型之间进行混合运算必然涉及类型的转换问题。

转换的方法有两种: 自动转换(隐式转换):遵循一定的规则,由编译系统自动完成。 强制类型转换:把表达式的运算结果强制转换成所需的数据类型。

**类型转换的原则:**占用内存字节数少(值域小)的类型,向占用内存字节数多(值域大)的类型转换,以保证精度不降低。

大 ==》 小有可能存在问题;小 ==》 大没问题;

c++ c语言 - 运算符和类型转换

隐式转换

**特点:**由编译器自动完成的类型转换

  • 算术运算式中,低类型转换为高类型
  • 赋值表达式中,表达式的值转换为左边变量的类型
  • 函数调用时,实参转换为形参的类型
  • 函数返回值,return表达式转换为返回值类型
#include <stdio.h>

int main(void){
    int i = -2;
    unsigned int j = 1;
    if( (i + j) >= 0 ){
        printf("i+j>=0\n");
    }
    else{
        printf("i+j<0\n");
    }
    printf("i+j=%d\n", i + j);
    return 0;
}

c++ c语言 - 运算符和类型转换

在计算时,转换为高类型,即unsigned int,判断>0,这里感觉没有错。那为什么输出-1,跟我们正常算-2+1的结果一样呢。

我们都知道计算机是补码存储,-2+1的unsigned int结果是0xffffffff,对于输出的%d其实是int类型,所以自然打印就是-1了。

强制类型转换

虽然自动类型转换不需要人工干预,使用方便,但有利也有弊,尤其当自动类型转换是从较高类型转换为较低类型时,将会降低精度或截断数据,可能得不到预期的结果。

为了给程序设计人员提供更多的类型转换控制权限,使程序设计更加灵活,转换的目的更加清晰,C 语言提供了可显式指定类型转换的语法支持,通常称之为强制类型转换。

强制类型转换的格式为:

(目标类型) 表达式
(目标类型) 变量
#include <stdio.h>

int main(void){
    float p = 3.6;
 int w = 4;
 double sum = (int)p*w;
 printf("输出浮点数:%lf",sum);
    return 0;
}

我们将p直接转成int类型,则p取整数部分进行运算

c++ c语言 - 运算符和类型转换

c++ c语言 - 运算符和类型转换
c++ c语言 - 运算符和类型转换

往期文章

2020-8-21




图 | 郭嘉

文 | 郭嘉





扫码关注桔梗与少年

新浪微博:桔梗与少年