C语言day01-整数

一、C语言-整数内部表达

  • 计算机内部一切都是二进制
  • 18 ===>0001 0010
  • 0 ===>0000 0000
  • -18 ===>?

1.如何表示一个负数

  • 十进制用“-”来表示负数,计算
    12 + (-18)  ==> 12 - 18 ==> -6
    12 - (-18)  ==> 12 + 18 ==> 30
    12 * (-18)  ==> -(12 * 18) ==> -216
    12 / (-18)  ==> -(12 * 18)
    

2.二进制负数

  • 一个字节:

    0000 0000 - 1111 1111 (0-255)

  • 二进制表示负数方案
    • 仿照十进制,设计特殊符号表示
    • 取中间的数为0,如1000 0000(128)表示0,比它大的是正数,比它小的是负数
    • 使用补码

3.补码

  • 考虑-1,十进制中:-1 + 1 = 0
    1 ==> (0000 0001);
    0 ==> (0000 0000);
    ? + (0000 00001) = (0000 0000);
    ? ==> (1111 1111);
    (1111 1111) + (0000 0001) = (1 0000 0000); 八位,多出来的丢掉
    
  • 因为 0 - (-1) = (-1),所以-1 = (1111 1111)
            (1 0000 0000) - (0000 0001) = (1111 1111)
    相当于==> 256 - 1 = 255
    (1111 1111)被当作纯二进制看待时,是255,被当作补码是-1
    
  • 补码的意义:拿补码和原码可以加出一个溢出的“零”;
  • 扩展:对于 -a,其补码就是 0-a,实际就是2^n - a,n是位数;

二、C语言-整数范围

  • 对于一个字节(8位),可以表达的是:

    0000 0000 - 1111 1111
    
  • 其中

    0000 0000 --> 0;
    1111 1111 ~ 1000 0000  --> -1 ~ -128;
    0000 0001 ~ 0111 1111  --> 1 ~ 127;
    
    1111 1111 ~ 1000 0000  --> -1 ~ -128;
    高位为 “1”:
        如果作为纯二进制数,是255 ~ 128;
        如果作为补码,就是表示符号位,是-1 ~ -128;
    
  • 实例:

    int main(int argc, char const *argv[])
    {
        char c = 255;
        int i = 255;
        printf("c = %d\n", c);      //c = -1
        printf("i = %d\n", i);      //i = 255
        return 0;
    }
    
    char是1个字节,c --> 1111 1111;最高位是1,所以是个负数
    int是4个字节,i --> 00000000 00000000 00000000 11111111;最高位为0所以为整数255;
    

1.unsigned

1111 1111 ~ 1000 0000  --> -1 ~ -128;
高位为 “1”:
    如果作为纯二进制数,是255 ~ 128;
    如果作为补码,就是表示符号位,是-1 ~ -128;

如果一个字面量常数想要表达自己是unsigned,可以在后面加u或者U

  • 255U
    int main(int argc, char const *argv[])
    {
        char c = 255;
        unsigned char c1 = 255;
        printf("char c = %d\n", c);                 //char c = -1
        printf("unsigned char c1 = %d\n", c1);      //unsigned char c1 = 255
        return 0;
    }
    
    unsigned 不以补码的形式,就是纯二进制,最高位的1不代表负号;
    
  • unsigned的设计初衷并不是扩展正数部分表达的范围,而是为了做纯二进制的运算,主要是为了移位。

2.整数越界

  • 整数以纯二进制方式进行计算的,所以:
    1111 1111 + 1 --> 1 0000 0000 --> 0
    0111 1111 + 1 --> 1000 0000 --> -128
    1000 0000 - 1 --> 0111 1111 --> 127
    

2.整数越界

  • 整数以纯二进制方式进行计算的,所以:
    1111 1111 + 1 --> 1 0000 0000 --> 0
    0111 1111 + 1 --> 1000 0000 --> -128
    1000 0000 - 1 --> 0111 1111 --> 127
    

image

image

三、C语言-格式化输入输出

整型:char,short,int,long,long long

在所输入输出时只用int或者long long

  • %d:charshortint (10进制打印)
  • %ld:longlong long
  • %u:unsigned
  • %lu:unsigned long long

例 1:

int main(int argc, char const *argv[])
{
    char c = -1;
    int i = -1;
    printf("c = %u\n", c);
    printf("i = %u\n", i);
    return 0;
}

输出:

c = 4294967295
i = 4294967295

分析:

char c = -1; 11111111
int i = -1;  11111111 11111111 11111111 11111111
i 和 c 作为printf的参数,编译器会把自动转换为int类型;
因为是有符号的所以扩展到全部位上都是1;
有因为“%u”以unsigned打印,所以4294967295

8进制和16进制

  • 一个以0开始的数字字面量是8进制
  • 一个以0x开始的数字字面量是16进制
  • 16进制很适合表达二进制数据,因为4位2进制正好是一个16进制
  • 8进制的一位数字正好表达3位二进制

* 实例2:

int main(int argc, char const *argv[])
{
    char c = 012;
    int i = 0x12;
    printf("c = %d\n", c);
    printf("i = %d\n", i);
    return 0;
}

输出:

c = 10
i = 18

* 实例3:

int main(int argc, char const *argv[])
{
    char c = 012;
    int i = 0x12;
    printf("八进制c = %o\n", c);
    printf("十进制i = %x\n", i);
    return 0;
}

输出:

八进制c = 12
十进制i = 12

四、整型的选择

  • 为什么整型分那么多种;
    • 为了准确表达内存,做底层程序的需要
  • 没有特殊需求就选择int
    • 现在的CPU的字长普遍是32位或64位,一次内存读写就是一个int,一次计算也是一个int,选择更短的类型不会更快,甚至更慢
    • 现代的编译器一般会设计内存对齐,所以更短的类型实际在内存中可能也占据一个int的大小
  • unsigned与否只是输出的不同,内部计算还是一样的。
posted @ 2022-08-06 13:04  DingJie1024  阅读(297)  评论(0编辑  收藏  举报