操作符/表达式/结构体/表达式求值

 

一.原码、补码、反码

1.二进制表示方式有三种:原码、补码、反码

       在32位计算机中整形占4个字节(即32位bite位),最高位符号位为0.代表为正数;负数的最高位为符号位为1。

       正数的原码、补码、反码都相同,而负数的原码、补码、反码需要经过计算。

原码到反码再到补码:

    反码计算方式:原码的符号位不变,其他位按位取反。

    补码计算方式:在反码基础上,符号位不变,反码加1。

而补码到原码:

    可用补码减1到反码,再将反码符号位不变,其他位按位取反。

    也可将补码符号位不变,先将其他位按位取反,再加1。

    负数原码、补码、反码计算方式如下图。

e20c8b710c7a40a9bb67175ce1091c68.png

例子

48fa62ba28674dcd9e072b39806e9f33.png

    若 unsigned int a=-10;将负数10转换为无符号整形,那么计算机不会将负数10的补码的最高位1当成符号位,而会将其当成有效位。

二.操作符

1.移位操作符

   A.左移操作符: <<

        移位规则:左边抛弃,右边补0,最高位自动变符号位。   

        指令表达方式:int n=-10;

                         n<<1;//表示负数10向左移动一位

        而在计算机内存中,存的是数字的补码:在程序中,printf打印的是数字的原码。

   B.右移操作符:>>

      移位规则:

      右移运算分两种:

             a.逻辑移位

                左边用0填充,右边丢弃。

             b.算数移位

                 左边用原该值的符号位填充,右边丢弃。

       注:移位不能移位负数,如n>>-2;

2.位操作符(补码状态进行计算)

    &:按位与

        两个数的二进制补码对应位相同为1,相异为0;

    |:按位或

        两个数的二进制补码对应位相有1为1,同时为0才为0;

    ^:按位异或

        两个数的二进制补码对应位相同为0,相异为1;

例.一道变态面试题:

//不允许创建临时变量,交换两个整数的内容
#include<stdio.h>

int main()
{
    int a = 2;
    int b = 3;
    //法一
    //a = a + b;//5
    //b = a - b;//2
    //a = a - b;
    //法2
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("a=%d\n", a);
    printf("b=%d\n", b);
    return 0;
}

3.单目操作符

   sizeof:

   计算操作数的长度,单位字节。

   字符串常量赋值给指针变量,赋值过去的是字符串常量首元素的地址。

    如char*p="abcdef"

    p为指针变量,存的是a的地址;

    *p表示解引用,通过找到地址进而找到元素a,而*p也可表示a(即*p=a)。

          sizeof后若跟变量名可省略括号,但后面若跟类型则不可省略。

          如:

                int a=10;

               printf("%d\n",sizeof(a));

               printf("%d\n",sizeof a);

               printf("%d\n",sizeof(int));

               //以上打印结果均为4;

          sizeof内部的表达式是不计算的

          如:

#include <stdio.h>
int main()
{
    int a = 10;
    short s = 5;
    printf("%d\n", sizeof(s = a + 3));
    printf("%d\n", s);
}//打印结果为分别为2;3

原因分析:在sizeof后面括号s=a+3不进行计算;

                  a为int类型,占4个字节,而s为short类型,占2个字节,当一个int类型强行塞进short类型时会发生截断,所以最后还是s说了算。

补充:int和char类型的指针所占大小均为4个字节或者8个字节,具体看编写环境是32位还是64位。

          sizeof返回的是无符号整形;

          指针补充:若arr为数组名,那么arr代表首元素的地址,所以*arr [ i ]也可写为*[arr +i]。

4.条件操作符

  exp1?exp2:exp3;

如:max=(a>b)?a:b;//若a>b为真,则max值为a;若为假,max值为b。

5.逗号表达式

  exp1,exp2:exp3......expn;

用逗号隔开的多个表达式,从左到右依次执行,结果取一个表达式的结果。

6.访问结构的成员

   ·

结构体 ·成员名

  ->

结构体指针->成员名

#include <stdio.h>
struct stu
{
    /*int a = 10;
    short s = 5;
    printf("%d\n", sizeof(s = a + 3));
    printf("%d\n", s);*/
    char name[10];
    int age;
    char sex[5];
    double score;
    
}
void set_age1(struct  stu stu)//传值
{
    stu.age = 18;//访问结构体中age的值
}
void set_age1(struct  stu* psstu)//传地址
{
    pstu->age = 18;//访问结构体中age的值
}
int main()
{
    struct  stu stu;
    struct  stu pstu;

    stu.age = 20;
    set_age1(stu);

    pstu->age = 18;
    set_age2(pstu);
    return 0;
}

7.隐式类型转换(偷偷转换类型)

  整形提升:表达式中的字符和短整型操作数在使用之前被转换为普通整形。

  整形提升针对的是小于整形的字节的类型,在整形提升过程中操作的是补码。

  负数和正数的整形提升高位补充符号位。

   实例

   char c1=-1;

    11111111(-1的补码)

    11111111111111111111111111111111(-1整形提升后的补码)

变量c1的二进制补码中只有8个比特位,所以在整形提升时高位补充符号位1

   实例

    char a,b,c;

    a=b+c;

具体过程:

     b和c的值会先被提升为普通整形(4个字节),然后再执行加法运算,加法完成后再赋值给a(a为char类型),结果会被截断,最后再储存到a里面。若需要将a以整形类型打印,需要在打印前将a整形提升再进行打印。

8.自增自减

    自增:++

    自减:--

    实例

    int a=1;

    int c=2;

    c=a++;

    printf("%d\n",a);//结果为3

    printf("%d\n",c);//先将a赋值给c,c再自增,结果为2

    c=++a;

     printf("%d\n",a);//结果为3

     printf("%d\n",c);//先将a自增,再将a自增后的值赋值给c,结果为3

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值