(笔记)运算符和表达式

C语言的运算符:

(1)算术运算符 (+ - * / %)             // % 只能对int型数据操作
(2)关系运算符 (> < == >= <= !=)
(3)逻辑运算符 (! && ||)
(4)位运算符 (& | ~ ^ << >>)
(5)赋值运算符 (=及其扩展赋值运算符)
(6)条件运算符 (? :)
(7)逗号运算符 (,)
(8)指针运算符  (* &)
(9)求字节数运算符 (sizeof)            //sizeof运算符
(10)强制类型转换运算符 ((类型))
(11)分量运算符 (. ->)
(12)下标运算符 ([])
(13)其他 (如函数调用运算符())

一.算术运算符和算术表达式

1 . 算术运算符: + - * / %

2 .算术表达式:用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子,称C算术表达式。运算对象包括常量、变量、函数等。

例如,下面是一个合法的C算术表达式:
    a*b/c-1.5+’a

3 .

C语言规定了运算符的优先级和结合性:

在表达式求值时,先按运算符的优先级别高低次序执行。
如果在一个运算对象两侧的运算符的优先级别相同,如a-b+c,则按规定的“结合方向”处理。

二.强制类型转换运算符

可以利用强制类型转换运算符将一个表达式转换成所需类型。
例如: (double)a (int)(x+y) (float)(5%3)

其一般形式为: (类型名)(表达式)

注意,表达式应该用括号括起来。如果写成 :(int)x+y,则只将x转换成整型,然后与y相加。

#include <stdio.h>
void main()
{
    float x;
    int i;
    x=3.6;
    i=(int)x;
    printf(“x=%f, i=%d\n”, x, i);
}
//结果:
// x = 3.6
// i = 3

三.自增、自减运算符

作用是使变量的值增1或减1,例如:
++i,- -i
i++,i- -
粗略地看,++i 和 i++的作用相当于i=i+1。但++i和i++不同之处在于

    ++i是先执行i=i+1后,再使用i的值;而i++是先使用i的值后,再执行i=i+1int i = 3;
    int j;
    j = i++;
    printf("j = %d\n",j);
    printf("i = %d\n",i);
    printf("i = %d\n",++i);   //先执行+1,再使用
    //结果: j = 3
            i = 4
            i = 5

注意:
(1)自增运算符(++)和自减运算符(–)只能用于变量,而不能用于常量或表达式,如5++或(a+b)++都是不合法的。

(2)++和- -的结合性是“自右至左”。

(3)自增(减)运算符常用于循环语句中,使循环变量自动加1;也用于指针变量,使指针指向下一个地址。

例子:
int i = 3printf("%d\n",-i++);
printf("%d\n",-++i);
printf("%d\n", i);
//输出结果:-3    分析: - 和 ++ 运算符优先级相同,结核性是“自右至左”
           -5
            5

有关表达式使用中的问题说明

(1)C运算符和表达式使用灵活,利用这一点可以巧妙地处理许多在其他语言中难以处理的问题。
但是应当注意:ANSI C并没有具体规定表达式中的子表达式的求值顺序,允许各编译系统自己安排。 (函数参数顺序点:变量值发送变化的位置点)

(2)C语言中有的运算符为一个字符,有的运算符由两个字符组成,在表达式中如何组合呢?

(3)在调用函数时,实参数的求值顺序,C标准并无统一规定。

1-1#include <stdio.h>
int main()
{
    int i = 3;
    printf("(i++)+(i++)+(i++) = %d\n",(i++)+(i++)+(i++));
    printf("i = %d\n",i);
    return 0;
}
//在Turb C 中:   12   63+4+5)= 12
//在VC中:         9   63+3+3)= 91-2int i = 0;
printf(“%d,%d,%d”,i++,i++,i++);
printf(“%d,%d,%d,%d,%d”, ++i, ++i,i++,++i,i++);
//Linux 2.14内核下
//从右往左算(先把输出的值压栈,再出栈)
//2 1 0
//5 5 2 5 0
//分析: 在Linux下, i++的逻辑和和其他环境一样
//      但是 ++i和i的进栈顺序是最后统一写入

例1-3#include <stdio.h>
#define MAN(a,b) a>b?a:b
int main()
{
    int a = 2;
    int b = 2;
    printf("the max is %d\n",MAN(++a,b));

    return 0;
}
(A)2 (B)3 (C)4 (D)5
//C

例1-4printf(“%d,%d,%d,%d,%d”, i++, ++i,i,i++ ,++i);
//3 4 4 1 42#include <stdio.h>
int main()
{
    int i = 3;
    int j = 2;
    printf("%d\n",i+++j);
    return 0;
}
//在C语言中规定:让从左到右运算符尽量组成一个数目多的运算符
//所以相当于: i++ + j = 2+3 = 53#include <stdio.h>
int main()
{
    int i = 3;
    //究竟是先从右往左还是从左往右,C语言中没有规定
    printf("%d,%d\n",i,i++);
    return 0;
}
//在Turb C 中:    4   3   从右往左算
//在VC中:         3   3   从左往右算

四.赋值运算符和赋值表达式

1.
赋值符号“=”就是赋值运算符,它的作用是将一个数据赋给一个变量。
如“a=3”的作用是执行一次赋值操作(或称赋值运算)。把常量3赋给变量a。
也可以将一个表达式的值赋给一个变量。

2.
如果赋值运算符两侧的类型不一致,但都是数值型或字符型时,在赋值时要进行类型转换。
(1)将浮点型数据(包括单、双精度)赋给整型变量时,舍弃实数的小数部分。

(2)将整型数据赋给单、双精度变量时,数值不变,但以浮点数形式存储到变量中。

(3)将一个double型数据赋给float变量时,截取其前面7位有效数字,存放到float变量的存储单元(32位)中。但应注意数值范围不能溢出。将一个float型数据赋给double变量时,数值不变,有效位数扩展到16位,在内存中以64位存储。

(4)字符型数据赋给整型变量时,由于字符只占1个字节,而整型变量为2个字节,因此将字符数据(8位)放到整型变量低8位中。

(5)将一个int、short、long型数据赋给一个char型变量时,只将其低8位原封不动地送到char型变量(即截断)。

(6)将带符号的整型数据(int型)赋给long型变量时,要进行符号扩展,将整型数的16位送到long型低16位中,如果int型数据为正值(符号位为0),则long型变量的高16位补0;如果int型变量为负值(符号位为1),则long型变量的高16位补1,以保持数值不改变。反之,若将一个long型数据赋给一个int型变量,只将long型数据中低16位原封不动地送到整型变量(即截断)

(7)将unsigned int型数据赋给long int型变量时,不存在符号扩展问题,只需将高位补0即可。

(8)将一个unsigned类型数据赋给一个占字节数相同的整型变量(例如:unsigned int->int,unsigned long->long,unsigned short->short),将unsigned型变量的内容原样送到非unsigned型变量中,但如果数据范围超过相应整数的范围,则会出现数据错误。

(8)将非unsigned型数据赋给长度相同的unsigned型变量,也是原样照赋(连原有的符号位也作为数值一起传送)。

1#include <stdio.h>
int main()
{
    int i;
    i = 3.12;   //舍弃实数的小数部分
    printf("%d\n",i);
    float f;
    double d;
    f = i;
    d = i;  
    printf("f = %f\n",f);
    printf("d = %lf\n",d);
    return 0;
}
//结果: 3
        f = 3.000000
        d = 3.0000002#include <stdio.h>
int main()
{
    float f;
    f = 123456789.0123456;

    printf("%f\n",f);
    return 0;
//输出结果:123456792.000000
//原因:只保留7为有效位  
3:  字符型数据赋给整型变量

//程序:
#include <stdio.h>
int main()
{
    unsigned char c1;
      signed char c2; 
    int i1,i2;

    c1 = c2 = '\376';    // 八进制376 对应 二进制 1111 1110
    i1 = c1;
    i2 = c2;

    printf("%d\n",i1);  //正数的补码即是它所表示的数的真值
    printf("%d\n",i2);  //负数的补码的数值部份却不是它所表示的数的真值
    return 0;
}
//输出:
      254
      -2

分析:

1、如果所用系统将字符处理为无符号的量或对unsigned char型变量赋值,则将字符的8位放到整型变量低8位,高8位补零。
如下:
这里写图片描述

2、如果所用系统将字符处理为带符号的(即signed char),若字符最高位为0,则整型变量高8位补0;若字符最高位为1,则高8位全补1。这称为”符号扩展”,这样做的目的是使数值保持不变。

这里写图片描述

4intshortlong型数据赋给一个char型变量

#include <stdio.h>
int main()
{
    int i = 289;
    char c = i;

    printf("%c\n",c);
    printf("%d\n",c);
    return 0;
}
//输出结果: !
           33

分析:

将一个int、short、long型数据赋给一个char型变量时,只将其低8位原封不动地送到char型变量(即截断)。例如:
(这里的int占2个字节)
这里写图片描述

5unsigned int 赋值给 int

#include <stdio.h>
int main()
{
    unsigned int a = 65535;
    signed  int b;
    b = a;
    printf("%d",b);
    return 0;
}
//int型占2字节的机器中
//在Turbo C 中输出: -1 

分析:
这里写图片描述

有符号数b,在计算机中以补码的形式存储,所以其对应的原码为: 1000000000000001(-1)。
这里就是因为unsigned型变量的内容原样送到非unsigned型变量中,但如果数据范围超过相应整数的范围,则会出现数据错误。

6signed int 赋值给 unsigned int

#include <stdio.h>
int main()
{
    unsigned int a ;
    signed  int b = -1;
    a = b;
    printf("%d",a);
    printf("%u",a);
    return 0;
}
//int型占2字节的机器中
//在Turbo C 中输出: -1        //%d是将a中的16位以有符号的形式输出,即以补码的形式
                   65535     //%u是将a中的16位以无符号的形式输出,

分析:
b = -1,在内存中以补码的形式存储,如下。
赋值给a 即 a = 1111 1111 1111 1111
这里写图片描述

符号扩展和截断总结:

符号位扩展:将一个位数低的数据赋值给位数高的数据 (char型 给 int型 ) 
     目的:保持数值的不变

     截断:将一个位数高的数据赋值给位数低的数据 (int型 给 char型)

3 . 复合的赋值运算符

在赋值符“=”之前加上其他运算符,可以构成复合的运算符。例如:
+= -= *= /= %= <<= >>= &= ^= |=

4 . 赋值表达式

由赋值运算符将一个变量和一个表达式连接起来的式子称为“赋值表达式”。它的一般形式为:
<变量> = <表达式>

赋值运算符左侧的标识符称为“左值”(left value)。并不是任何对象都可以作为左值的,变量可以作为左值,而表达式a+b就不能作为左值,常变量也不能作为左值,因为常变量不能被赋值。

出现在赋值运算符右侧的表达式称为“右值”(right value)。
显然左值也可以出现在赋值运算符右侧,因而凡是左值都可以作为右值。

a = b =c =3;
//赋值表达式的结合性是:从右往左,即先对C赋值3。

五.逗号运算符和逗号表达式

C语言提供一种特殊的运算符—逗号运算符。用它将两个表达式连接起来。例如:
3+5, 6+8
称为逗号表达式,又称“顺序求值运算符”。逗号表达式的一般形式为:
表达式1, 表达式2
逗号表达式的求解过程是:先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值。

逗号表达式的优先级最低。

#include <stdio.h>
int main()
{
    //int i = 3+5,6+8; 这样申明会出现错误,逗号表达式的优先级最低。
    int i = (3+5,6+8);
    printf("%d",i);
    return 0;
}
//输出结果: 14
#include <stdio.h>
int main()
{
    printf("%d",(3+5,6+8));
    return 0;
}
//输出结果: 14

例题:

这里写图片描述

#include <stdio.h>
main()
{
    int i=99;
    char c;
    unsigned int ui;
    float f;
    long int li;

    c=i;    //c='c'
    ui=i;   //ui=99
    f=i;    //f=99.0
    li=i;   //li=99

    printf("c=%c\n", c);
    printf("ui=%u\n", ui);
    printf("f=%f\n", f);
    printf("li=%ld\n", li);  
}

#include <stdio.h>
main()
{
    int i;
    char c = 'd';
    unsigned int ui;
    float f;
    long int li;

    i=c;    //100
    ui=c;   //100
    f=c;    //100.000000
    li=c;   //100

    printf("i=%d\n", i);
    printf("ui=%u\n", ui);
    printf("f=%f\n", f);
    printf("li=%ld\n", li);  
}

#include <stdio.h>
main()
{
    int i;
    char c ;
    unsigned int ui;
    float f = 53.65;
    long int li;

    i=f;    //53
    c=f;    //53
    ui=f;   //53
    li=f;   //53

    printf("i=%d\n", i);
    printf("c=%d\n", c);
    printf("ui=%u\n", ui);  
    printf("li=%ld\n", li);  
}

这里写图片描述

main()
{
    int a=12;
    printf("a+=a %d\n", a+=a);      //a=a+a             24
    printf("a-=2 %d\n", a-=2);      //a=a-2             22
    printf("a*=2+3 %d\n", a*=2+3);  //a=a*(2+3)=22*5    110
    printf("a/=a+a %d\n", a/=a+a);  //a=a/(a+a)          0
    int n=5;
    printf("a%=(n%=2) %d\n", a%=(n%=2));    //a=a%1      0
    printf("a+=a-=a*=a %d\n", a+=a-=a*=a);               0
                             //复合赋值运算符结合性:从右往左
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值