2019-05-19 C 基础回顾(1)

作者: 银TaMa | 来源:发表于2019-05-19 10:27 被阅读0次

    C 基础回顾

    1.读程序求输出

    #include<stdio.h>
    int i = 2;
    int main(){
        int i = i;
        printf("%d\n",i);
    }
    

    编译可以通过,不过会有警告,因为

    int i = i 企图使用自己初始化自己,用一个未初始化的去初始化自己,没用。

    2. 读取程序求输出

    #include<stdio.h>
    int func(int x){
        int cnt = 0;
        while(x){
            ++cnt;
            x = x & (x - 1);
        }
        return cnt;
    }
    int main(){
        printf("%d\n",func(9999));
        return 0;
    }
    

    x & x - 1 :干啥了呢?

    去掉了最后一位的1

    x & (-x) =》lowbit(x)的意思是将 x 转化成二进制数之后,只保留最低位的1及其后面的0,截断前面的内容,然后再转成10进制数。

    3 . 用位运算实现两个整数的加法运算。

    1. 递归
    int getSum(int a, int b){
        return a == 0 ? b : getSum((unsigned)(a & b) << 1,a ^ b);
    }
    
    1. 迭代
    int getSum(int a, int b){
        while(a){
            b = a ^ b;
            a = (unsigned)(a & (b ^ a)) << 1;
        }
        return b;
    }
    

    ​ a ^ b : 无进位的相加 ,

    ​ a & b : 每一位的进位 ,

    补充:

    ​ (a & b) + (a ^ b) << 1,求的是(a + b)/ 2 ,注意的是unsigned 来处理负数。所以说1+-2也是可以的,因为-2 是用补码的形式在内存中存储的,所以说可以和正数的相加一起处理。

    补充:

    ​ -b = ~b+1

    ​ 所以a - b => return getSum(a,getSum(~b,1));

    4.以下程序输出是啥

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <conio.h>
    using namespace std;
    int main() {
        float a = 1.0f;
        cout << (int)a << endl;
        cout << &a << endl;
        cout << (int &)a << endl;
        cout << boolalpha << ((int)a == (int&)a) << endl; ??
        float b = 0.0f;
        cout << (int)b << endl;
        cout << &b << endl;
        cout << (int &)b << endl;
        cout << boolalpha << ((int)b == (int&)b) << endl; ??
        return 0;
    }
    

    推荐阅读:

    强制类型转换(int)、(int&)和(int*)的区别

    (int)x 强制类型转换,是将浮点数x为参数构造整数(即float转换为int)

    (int &)y 则是告诉编译器将y看成int对待(内存里的数据不做任何转换),所以(int &)x值为1071 644 672。
    至于(int*)的话,我就不多说啦,就是强制转换成整型指针,一般人们容易混淆的是(int)和(int&)这两个。

    补充:浮点数0.0是比较特殊的,它并不按照上面说的浮点数的格式存储,浮点数0.0在内存里的存储是000.....000(全零)。

    5. 以下这段程序的输出是啥?

    #include<stdio.h>
    int main(){
        unsigned int a = 0xFFFFFFF7;
        unsigned char c = (unsigned char)a;
        char *b = (char *)&a;
        printf("%08x,%08x\n",c,*b);
        return 0;
    }
    
    1. 大小端 推荐阅读  详解大端模式和小端模式

      举一个例子,比如数字0x12 34 56 78在内存中的表示形式。

    1)大端模式:Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。(其实大端模式才是我们直观上认为的模式,和字符串存储的模式差类似)

    低地址 --------------------> 高地址
    0x12 | 0x34 | 0x56 | 0x78

    2)小端模式:Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

    低地址 --------------------> 高地址
    0x78 | 0x56 | 0x34 | 0x12

    可以编写一个小的测试程序来判断机器的字节序:

    BOOL IsBigEndian()  
    {  
        int a = 0x1234;  
        char b =  *(char *)&a;  //通过将int强制类型转换成char单字节,通过判断起始存储位置。即等于 取b等于a的低地址部分  
        if( b == 0x12)  
        {  
            return TRUE;  
        }  
        return FALSE;  
    }
    

    联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写:

    BOOL IsBigEndian()  
    {  
        union NUM  
        {  
            int a;  
            char b;  
        }num;  
        num.a = 0x1234;  
        if( num.b == 0x12 )  
        {  
            return TRUE;  
        }  
        return FALSE;  
    }
    
    1. 整数提示 推荐阅读 整数提升

    ​ C99标准中有明确提到整数提升的概念:"如果int能够表示原始类型中的所有数值,那么这个数值就被转成int型,否则,它被转成unsigned int型。这种规则被称为整型提升。所有其它类型都不会被整型提升改变。"

    ​ 为什么会有整数提升?这是因为对于int类型数据作运算时,CPU运算速度是最快的,所以C语言会对数据作整数提升的处理,使得程序的运行速度尽可能地快

    比如下面的这个例子:

    int main()
    {
       char a=127;
       unsigned char b=255;
       short c=32767;
       unsigned short d=65535;
     
       printf("char: a+1=%d %d\n",a+1,sizeof(a+1));
       printf("uchar: b+1=%d %d\n",b+1,sizeof(b+1));
       printf("short: c+1=%d %d\n",c+1,sizeof(c+1));
       printf("ushort: d+1=%d %d\n",d+1,sizeof(d+1));
     
       return 0;
    }
     
    结果:
    char: a+1=128 4
    uchar: b+1=256 4
    short: c+1=32768 4
    ushort: d+1=65536 4
    

    针对源题目

    1. 在小端的机器上c = 0xF7;大端就是0xFF
    2. b 存在整数提升,又因为是负数,所以自动补1结果就是0xFFFFFFF7

    6. 以下程序输出结果是

    #include<stdio.h>
    int main(){
        unsigned char a = 0xA5;
        unsigned char b = ~a>>4+1;
        printf("%d\n",b);
        return 0;
    }
    

    这个就是上述的整数提升过程,~a >> 5

    5 是int 所以会将~a 提升到int 4 字节

    然后截取1字节赋值给b。

    7.不用”if“,”?:“,”switch“或其他判断语句,求两个数中较大的数或较小的数

    int Find1(int a, int b) {
        return ((a + b) + abs(a - b)) / 2;
        //return ((a + b) - abs(a - b)) / 2;
    }
     
    /*
    当a大于b时,a-b为正,右移sizeof(int) * 8 - 1后,最右侧一位为0,0^1 = 0;
    当a小于b时,a-b为负,右移后最右侧一位为1,1^1 = 1
    */
    int Find2(int a, int b) {
        int c[2] = {a, b};
        int z = a - b;
        z = (z >> (sizeof(int) * 8 - 1)) & 1;
        return c[z];
        /*
        int c[2] = {b, a};
        int z = a - b;
        z = (z >> (sizeof(int) * 8 - 1)) & 1;
        return c[z];
        */
    }
     
    int Find22(int a, int b) {
        int flag = ((a - b) >> (sizeof(int) * 8 - 1)) & 1;
        return (a - (a - b) * flag);
        //return (b - (b - a) * flag);
    }
    

    相关文章

      网友评论

        本文标题:2019-05-19 C 基础回顾(1)

        本文链接:https://www.haomeiwen.com/subject/poufzqtx.html