ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

---- 招聘之C语言 ----

2021-03-30 18:58:50  阅读:119  来源: 互联网

标签:字节 -- 招聘 补码 ++ C语言 ---- int 地址


C语言测试第一轮【错题涉及知识点】
内核原理{
    原码与反码{                  
        2^8 = [-128,-127,-126...0...+125,+126,+127][-128,-127,-126...0...+125,+126,+127]
        补码 = [10000001,11111111~00000000,01111111][10000001,11111111~00000000,01111111] 
        //如果溢出赋值了+128 --> 128%127 == 1 --> -128   (从左向右第一个)         
        //如果溢出赋值了-129 --> -129%-128 == -1 --> 127 (从右向左第一个)
        //-128的补码 == 1000 0000 == 负数最小开头
        //-127的补码 == 1000 0001 == 负数最小开头+1
        //-126的补码 == 1000 0010 == 负数最小开头+2
        //  -1的补码 == 1111 1111 == 负数倒数第一个    
        //  +0的补码 == 0000 0000 == 正数最小开头
        //  +1的补码 == 0000 0001 == 正数最小开头+1
        //  +2的补码 == 0000 0010 == 正数最小开头+2
        //知道取值范围,能直接写出补码,补码没有-0,-0就是-128,只有+0
        //补码解决了符号位不能参与运算的问题,解决了-0与+0的问题
        //补码 --> 原码(补码求补码)        
        //用户提供原码 --> 补码计算 --> 原码交给用户
        //1个字节 --> 2^7=128 --> [-128,127]
        //2个字节 --> 2^15=32768 --> [-32768,32767]
        //4个字节 --> 2^31=2147483648 --> [-2147483648,2147483647]
        例题:-1+2=1
        -1 = 11111111(补码)
        +2 = 00000010(补码)
        结果:00000001(补码)--> 00000001(原码)

        例题:-2+1=-1
        -2 = 11111110 (补码)
        +1 = 00000001 (补码)
        结果:11111111 (补码)-->10000001 (原码)
    }

    内存分配{
        16位平台{
            char        1个字节8位 
            short       2个字节16位 
            int         2个字节16位 //*
            long        4个字节32位 
            地址/指针     2个字节16位  
        }  
        32位平台{
            char         1个字节8位 
            short        2个字节16位 
            int          4个字节32位 
            long         4个字节32位
            long long    8个字节64位  
            地址/指针     4个字节32位 
        }  
        64位平台{
            char      1个字节 
            short     2个字节
            int       4个字节 //*
            long      8个字节 
            long long 8个字节  
            指针/地址  8个字节 //*
        }  
        内存分区{
            栈区{
               “函数参数”,“函数内的局部变量”  
                //栈空间默认初始化为随机值 
                //栈区的地址分配是从内存的高地址开始向地地址分配
                //用户变量存放在栈区,内容存放在其他区,所以才需要指针指向目标
                例题{
                    int i=0x22222222; 
                    char szTest[]=0x61616161;
                    func(I, szTest); 
                    请问刚进入func函数时,参数在栈中的形式可能为 (左侧为地址,右侧为数据)
                    0x0013FCF0    0x0013FCF8  //函数入口地址
                    0x0013FCF4    0x22222222  //先放栈顶,从高地址-->低地址放
                    0x0013FCF8    0x61616161  //函数参数从右向左入栈,从左向右出栈
    
                    }
            }
            堆区{
                又称树,由程序员分配和释放,若程序员忘记释放,进程结束时,自动销毁 
                //程序结束时由操作系统回收 
                //堆空间默认初始值为0
            }
            bss段{
                “未初始化的全局变量”,“未初始化的静态变量”
                BSS是Block Started by Symbol的简称,BSS段属于静态内存分配,
                静态变量仅在第一次创建时初始化一次,之后自动跳过初始化语句,系统将自动将其值设置为0      
                动态内存分配是在程序运行时分配内存,静态内存在装入时分配内存
                              
            }
            数据段{
                用户初始化过的bss段就数据段
            }
            代码段{
                “函数体的二进制代码”,属于只读,不可更改,字符串常量就放在代码段
            }
        }        
        写入内存与读取内存{
            大端与小端的存放与读取数据{
                //数据都是从低地址向高地址存放,从高字节的一头读出数据,不是从必须从高地址读
                //一般计算机都是小端模式,从低字节放,从右向左放,从左向右取,是属于栈操作;
                大端 = 先放高字节,先放前面
                0x1234 --> |0x12(低地址)|0x34(低地址+1)|
                小端 = 先放低字节,先放后面
                0x1234 --> |0x34(低地址)|0x12(低地址+1)|
            }
        }            
    }  
}



数组{
    二维数组{
        int a[3][3] -->
                        0 1 2
                        3 4 5
                        6 7 8
        //二维数组类似与一栋楼,a[3][3]表示三层楼,每层楼三间房1,2,3,a表示楼下入口
        //“+”表示找到,“*”表示进入,“[]”==“+”+“*”
        //必须先进入楼层再进入房间==先取行内容,再取列内容
        //1个*表示进入楼层走廊,2个**表示进入房间,一个[]表示进入楼层走廊,2个[][]表示进入房间
        //a[1][1]           ,找到2楼,进入2楼,找到2号间,进入2号间
        //*(*(a+1)+1)       ,找到2楼,进入2楼,找到2号间,进入2号间         
        //a[1]+1            ,找到2楼,进入2楼,找到2号间
        //a[1]              ,找到2楼,进入2楼,找到0号间
        //a[1]+0            ,找到2楼,进入2楼,找到0号间
        //*(a+1)            ,找到2楼,进入2楼
        //*((int*)(&a+1)-1) ,&a+1根据a整栋楼的地址,找到a旁边一栋楼的地址,
                              再返回减1一个房间的地址等于a的最后一个房间地址
        
    }
    
}

运算
{
    优先级{
        
    }
    ++{
        ++只能作用于变量,数字或表达式都是错(有符号的都叫表达式例如1+1,a++)
        i++:先自增,再返回自增之前的值
        ++i:先自增,再返回自增之后的值
        题{
            a++b  (x)
            a+++b == (a++)+b == a+(++b) (√)
            a++++b (x)
    
            i=1;(++i)+(++i)+(i++)+(i++) = 2+3+3+4;
            //不同编译器对++运算的规定不一样,不同编译器结果不一样,实际最好不用++;

            
            char a[] = “hello” ;a++; -->地址常量不能自加
        }
    }
    表达式{
        后缀表达式{
            a - (b * c + d) / e = bc* --> bc*d+ --> bc*d+e/ --> abc*d+e/-

            a+b*c-(d+e)/f = --> de+ --> de+f/ =abc*+def/-
                            --> bc* --> abc*+
                          

        }
        逗号表达式{            
            (a=2,b=3,b++,a+b) 《==》 a=2;b=3;b++;a+b; //最后值为a+b //逗号表达式中间必须有表达式
        }
    }
    sizeof{
        //sizeof属于运算符 //sizeof(void)提示“不允许使用不完整的类型”,报错
        //sizeof中的任何运算都不会执行,比如sizeof(++i); ++i是不会执行的
        //sizeof()可以不统计到\0,如果有要算上\0;
        //strlen()直到统计到\0为止,但是不算上\0
        例1{
        int getSize(int data[]) { return sizeof(data); }
        int main(){//64位机子
            int data1[] = {1,2,3,4,5};
            int* data2 = data1;            
            int size1 = sizeof(data1); //20字节       
            int size2 = sizeof(data2); //8字节       
            int size3 = getSize(data1);//8字节     
        }
    强制转换{
            无符号号整数和有符号整数相加,有符号整数转化为无符号整数            
            float型转换为int型,小数点后的数位丢失
            int型转换为float型,整数位可能丢失,浮点表示的整数范围比int小
            
            2字节强转成1字节只是取最第低字节
            11111111 00000000 --> 00000000
            比如(bool*)(int*)1024 --> 10000000000 --> 自取最后第一个位==0
        }
    标识符{
        标识符 = 标识符开头(“字母”,”_“,"") + 标识符中间(“字母”,”_“,"")+标识符中间(“字母”,” 
“
​	
 ,"","数字")
        //只是开头不能用数字,其他一模一样        
        }
    位运算{
        ^ 异或 = 加;C中没有同或
        %要求两边都是整数
        关系运算符具有左结合性,(’a'<c<=’z’)先求’a'<c的值,即为0(假),再求0<=’z’的值,即为1(真)
        逻辑运算符两侧运算对象的数据类型可以是任何类型的数据      
        
        }
    逻辑运算{
        0&&n++; //n++不会执行
        1||n++; //n++不会执行

        }
    赋值运算{
        i*=j+8 <==> i = i*(j+8)
        }
    运算优先级{
        
               

              //括号 > 单目运算 > 算数运算 > 箭头运算 > 位运算> 逻辑运算 > 赋值运算
              //从左向右依次运算
        }
    }
}


函数{
    函数传递参数{
        C语言中实参和形参都是值复制传递,只能传递“数据的值”与“地址的值”,指针是不能传递的
        各自使用独立的存储单元,两者井水不犯河水,所以实参和虚参各占一个独立的存储单元
        
        子函数自己定义的栈空间地址返回给调用函数,地址内容会发生变化,不能得到想要的值!
    
    }
}

库函数{
    函数{
        例题1{
            int fun(int i = 1, int j = 2) //函数在定义时,可以默认有初值
            {
                return (i + j); //则fun(3)的值为:3+2=5 //则fun()的值为:1+2=3
            }
        }
        例题2{
            f(printf("a"),printf("b"),printf("c"));-->cba//参数从右边执行从右边入栈         
            printf("%c\n",a,b); -->a //从左向右出栈

        }
    }
    scanf{
        %s得到一个连续的字符串,遇到空格、回车会自动终止
        scanf将所有读到的内容送入缓冲区队列,再根据所需出队列,赋值给地址
        scanf("%d%c",&a,&b); 
        //键盘输入10A,将”10A“存放在缓冲队列,按照需求出队数字10给a地址,出队A给b地址
    }
    fork{
        父子进程都是用的虚拟地址空间。num地址的值相同,都是一样的逻辑地址

        例题1{
            int main(void)
            {
                fork();
                printf("hello\n");
                fork();
                printf("hello\n");
            }
            
            -->打印6个hello  
            //第一次fork,一共两个进程,打印两次
            //第二次fork,一共四个进程,打印四次
            //所以一共6个
        }        

    }
    main{
        argc:程序名和参数个数之和
        argv[0]记录的是程序名,系统自动加载进去的,后面的argv[i]记录的输入参数
    }
    printf{
        %#  //带符号输出
        %0  //补0
        %5  //至少输出5位
        %.2 //浮点数小数点后四舍五入输出2位,只输出2个字符 //%5.2,只输出2个字符其余三个用空格,右对齐
        %-  //左对齐
        %+  //默认右对齐
        %*  //跳过不读
        %e  //“实数e整数”或“实数E整数”,e或E前后的实数和整数(可以带符号:e+4)都"不能省略",
            小数点前后的数字都可以不写        
        %l  //long
        %f  //double
    }
    malloc{
        malloc和free申请和释放的虚拟堆内存。并不是物理内存。
        malloc函数是动态内存分配,属于执行阶段进行内存分配,地址重定位
    }
    strcat{
        strcat(p1+2,p2+1);
        //将p2+1开始的字符串添加到p1+2字符串的末尾(覆盖p1+2后的\0"),返回以p1+2为首的字符串,即"cdBCD"
    }
    strcpy{
        strcpy(str+2,strcat(p1+2,p2+1)); //将"cdBCD"copy到str+2位置上,并覆盖后面内容,返回str地址
    }
    fopen{
        //r读,w写,b二进制文件,a追加,t文本文件,+读写
        //只有w,w+,每次会清空
        //只有r,r+必须要求文件存在
        //只有a,a+会保留文件原先的内容
        r    以只读方式打开文件,该文件必须存在。
        r+    以读/写方式打开文件,该文件必须存在。
        rb+    以读/写方式打开一个二进制文件,只允许读/写数据。
        rt+    以读/写方式打开一个文本文件,允许读和写。
        w    打开只写文件,若文件存在则长度清为 0,即该文件内容消失,若不存在则创建该文件。
        w+    打开可读/写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
        a    以附加的方式打开只写文件。写入的数据会被加到文件尾,即文件原先的内容会被保留
        a+    以附加方式打开可读/写的文件。写入的数据会被加到文件尾后,即文件原先的内容会被保留
        wb    以只写方式打开或新建一个二进制文件,只允许写数据。
        wb+    以读/写方式打开或建立一个二进制文件,允许读和写。
        wt+    以读/写方式打开或建立一个文本文件,允许读写。
        at+    以读/写方式打开一个文本文件,允许读或在文本末追加数据。
        ab+    以读/写方式打开一个二进制文件,允许读或在文件末追加数据。
    }
    gets{
        gets是得到一整行的字符串;//从输入缓冲区全部赋值给用户
    }
    getchar{
        得到一个字符;
    }
    strlen{
        //strlen()直到统计到\0为止,但是不算上\0
        
        b[] = {'x', 'y', 'z'}; strlen(b); --> b没有'\0',strlen一直向后搜索,结果大于等于3!
        
    }
}

结构体{
    结构体{
        结构体变量之间的copy赋值直接”=“

        char data[0]柔性数组,它只能放在结构体末尾,是申明一个长度为0的数组,支持对于数组data的越界访问
        可以使得这个结构体是可变长的,这是在C99才加入标准的,可以构造出变成结构体,如缓冲区,数据包等等
        
        
        struct {int a; double b; char c;} A; sizeof(A)的返回值是3×8=24
    }
    union{

    }
    enum{

    }

}


数据类型{
    register{
        寄存器变量,该变量值在寄存器中存放
    }
    字符{
        数字赋值给char类型时不用加单引号
        ‘%%’ = %
        


    }
}

编译{
    预处理{//粗暴的替换
        #include<> //只从标准库文件目录下搜索
        #include"" //首先从用户工作目录下开始搜索,然后搜索整个磁盘。

        #define INT_PTR int*  --> INT_PTR a,b; --> int*a,b //b是整形
        typedef int*int_ptr; -->  int_ptr c,d; --> int*c,int*d

        #define N 3
        #define Y(n)((N+1)*n)
        z=2*(N+Y(5+1)) == 2×(3+((3+1)×5+1))== 28 
        //宏定义时,必须对参数用()进行包起来的原因,控制计算优先级,而不是傻乎乎的替换
    }
    编译{        
        char相当于signed char或者unsigned char,但是这取决于编译器!
    }
}

指针{
    没有初始化的野指针不能参与运算
    
    指针为NULL,没有指向任何变量,不能对该指针进行操作
    
    int(*p)[4] //()把*p包起来表示这是一个指针,后面【】表示数组,所以表示一个指针指向数组
    int(*P)(void) ;//表示函数指针
    int* p(void); //表示函数

}

其他{
    时间复杂度{
        程序运行了n次才能完,所以时间复杂度就是O(n),
        比如:for(i=0;i<n;i++) --> O(n) //需要运行n次才结束
            for(i=0;i<n*n;i++)--> O(n*n)//需要运行n×n次才结束
    }
    线程{
        ++a和printf不是原子指令,可随时被打断
        好东西才会被大家一起享用嘛,所以高速设备一般被设置成共享设备。    
    }    
    其他{        
        x = x & (x – 1); == 求x二进制表示中含有1的个数。
        
        编译错误分为编译错误和链接错误

    }
    
}


标签:字节,--,招聘,补码,++,C语言,----,int,地址
来源: https://blog.csdn.net/qq_42150119/article/details/115332742

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有