zoukankan      html  css  js  c++  java
  • 20160206.CCPP体系具体解释(0016天)

    代码片段(01):.指针.c+02.间接赋值.c
    内容概要:内存

    ///01.指针
    #include <stdio.h>
    #include <stdlib.h>
    
    //01.取地址操作符(&)具体解释:
    //  1.操作对象:变量名(实质:内存实体|数据实体)
    //  2.操作特点:属于寄存器操作(操作结果不是内存实体)
    //      (1).取地址操作(&变量名)是在CPU的寄存器区域所完毕的操作;
    //      (2).地址数据不占用内存,内存地址是在CPU核心构成组件寄存器产生的,
    //          内存地址的数值和内存存储没有实质关系;
    //  3.计算机地址总线:连接CPU与硬件内存的总线
    //      (1).总线数目与CPU位数+操作系统位数有关
    //      (2).地址数值作为一个常量恒久不变
    //      (3).地址作为产量恒值并不会占用内存
    //          内存地址是在CPU的寄存器其中产生的,因此不具备内存实体,也就不会占用内存
    //      (4).总线的个数决定者位数的不同:
    //          32条总线相应于32位操作系统;64条总线相应于64位操作系统
    //02.对指针变量的解释:
    //  P一个指针变量,用于存储普通变量的地址数值,然后通过操作指针变量的方式间接操作普通变量
    //03.对于指针所占用的字节数分析:
    //  Win32平台所编译的程序的指针类型占用4个字节
    //  Win64平台所编译的程序的指针类型占用8个字节
    int main01(void)
    {
        int num = 10;
        int data = 20;
        //P是一个指针变量,能够存储相同类型的不同变量的内存地址,经常使用于做间接訪问变量本身(内存实体)操作
        int * pNum = &num;//0x12312312
        int * pData = &data;
        printf("%d 
    ", sizeof(pNum));//指针变量所占用的内存尺寸为4个字节(Win3平台所编译的程序)
        printf("%p 
    ", pNum);//直接打印指针变量(pNum)的数值,相当于间接打印了普通变量(num)的地址
        printf("%p 
    ", &pNum);//表示获取"指针"变量的地址,类型为int **
    
        system("pause");
    }
    
    //04.指针变量内容具体解释:
    //  1.类型:
    //      既决定了内存实体步长,也决定了内存实体解析方式
    //  2.数值:
    //      就是一个地址数值
    //  3.场景:(携带*号的情况)
    //      赋值号左边:
    //          给内存实体写入数据
    //      赋值号右边:
    //          从内存实体读取数据
    int main02(void)
    {
        int num1 = 1100;
        int num2 = 1200;//变量num都分配了内存,内存实体(数据实体)的数值代表变量的数据
        int * pNum = &num1;//pNum1是int类型的一级指针变量,&num1是一级指针真常量数值(含有类型含义)
        pNum = &num2;//pNum的值是num2这个变量(内存实体|数据实体)的内存地址,该内存地址统一占用4个字节,int * 地址,指针变量的长度统一为4
        //int * 对称于pNum,指针类型既决定了内存实体的訪问字节步长,也决定了内存实体的解析方式,特殊点:浮点型数据的特殊存储形式,既是指数形式存储还涉及到无符号类型(存储实质阶码)
        *pNum = 12;//通过指针变量间接的訪问了普通变量的内存实体//依据指针数值找到内存地址,依据指针类型既决定了存储步长也决定了存储方式
        printf("%p 
    ", &pNum);//&pNum表示获取一级指针变量pNum的内存地址,该地址数值存储于CPU核心组件寄存器区域,全然不会占用内存存储
        printf("%d 
    ", num2);
        printf("num2 = %d 
    ", num2);
    
        system("pause");
    }
    
    //05.野指针:就是没有进行初始化操作的指针变量
    //  VC:编译检測,GCC编译不检測
    //06.解析方式的不同含义:
    //  有无符号:signed/unsigned
    //  存储原理:补码原理/阶码原理
    //07.指针变量所占用的内存尺寸仅仅跟编译平台有关:
    //  Win32平台:4字节-->Win64平台:8字节
    int main03(void)
    {
        //int * p;//没有对象的野指针,定义指针变量的时候必须进行指针变量的初始化操作
        //printf("%p 
    ", p);//打印指针变量其中所存储的内存地址-->编译不通过
    
        //解析方式的不同特点:
        //  signed/unsigned(仅仅针对于10进制的整数)+float指数形式存储(阶码实质存储)
        int num1 = 10;
        int num2 = 20;
        //float * pNum;
        //pNum = &num1;
        //printf("%f", *pNum);//指针变量的类型决定了指针变量对其所存储的地址数值的解析步长(字节尺寸)以及解析方式(补码阶码)
        int * pNum;
        pNum = &num1;
        printf("%d 
    ", *pNum);//对内存地址数值的正确解析步长和正确解析方式
        printf("%d 
    ", sizeof(pNum));//指针变量所占用的字节长度在Win32平台之下统一占用4个字节的内存尺寸,不论什么类型的地址都一样採用int类型的统一字节尺寸存储
        printf("%d 
    ", sizeof(*pNum));//尺寸,方式
    
        system("pause");
    }
    
    //08.指针认识规律:
    //  *pNum<=>num
    int main04(void)
    {
        int num = 20;
        int data = 30;
        int * pNum = &num;//int类型的一级指针变量存储了int类型的普通变量的内存地址
        //&num = 1;//内存地址不同意操作,由于&num这个表达式是在CPU的寄存器其中所进行的操作,然而C语言是不能够直接改动寄存器其中的数据的
        //pNum = &data;
        num = 3;
        printf("%d,%d 
    ", *pNum, num);//*pNum和num是全然等价的
        *pNum = 7;
        printf("%d,%d 
    ", *pNum, num);
    
        system("pause");
    }
    ///02.间接赋值.c
    #include <stdio.h>
    #include <stdlib.h>
    
    //01.函数形參具有副本机制:
    //  1.传值和传指的数据层面意思都一样;
    //      仅仅只是对相同的数值有着不同的解析方式!
    //  1.函数的副本机制总是存在;
    //      不管是传值还是传地!
    void change05(int num)//函数形參具有副本机制
    {
        //函数形參具有副本机制,因此,不管是传值还是传指,都具备这种特性:
        //  传值传递的是副本,传指传递的是地址,因此出现不一样的改动效果
        //  实质:都是副本,仅仅只是对待相同的数值解析方式不同而已
        num = 3;
        printf("change05 = %d 
    ", num);
    }
    
    int main05(void)
    {
        int num = 10;
        change05(num);
        printf("%d 
    ", num);
    
        system("pause");
    }
    
    void change06(int * pNum)
    {
        *pNum = 3;
    }
    
    int main07(void)
    {
        int num = 10;
        change06(&num);//&num-->表达式-->没有内存实体-->位于寄存器-->C语言不具备改动寄存器的权限
        printf("%d 
    ", num);
    
        system("pause");
    }

    程序片段(02):01.Run.c
    内容概要:

    #include <stdio.h>
    #include <stdlib.h>
    
    //01.外挂改动数值原理
    //  1.注入DLL模块儿
    //  2.依据指针进行跨函数訪问内存
    _declspec(dllexport) void go()
    {
        int * p = (int *)0xae0720;
        *p = 77;
    }
    
    //02.遍历内存查找原理:
    //  1.单字节内存遍历
    //  2.待查找尺寸读取
    _declspec(dllexport) void run()
    {
        typedef char * Char;
        for (Char  pStart = 0xae000000,pEnd = 0xae100000; pStart < pEnd; ++pStart)//单字节遍历指定内存范围
        {
            int * p = (int *)p;//指针类型转换,待查找尺寸读取数据进行匹配,以便于相同数值进行内存检索
            if (77 == *p)
            {
                *p = 86;
            }
        }
    }

    程序片段(03):01.void.c+02.空指针.c
    内容概要:Void与空类型指针

    ///01.void.c
    #include <stdio.h>
    #include <stdlib.h>
    
    //01.空类型与空类型指针:
    //  空类型:void
    //  空类型指针:void *
    //02.指针类型:
    //  解析步长+解析方式
    //03.空类型指针变量:
    //  能够存储不论什么类型的指针
    int main01(void)
    {
        //error C2182:"a":非法引用"void"类型 void
        int num = 10;
        double db = 19.3;
        //void num;//不合法-->没有明白数据类型-->编译器既不知道分配多大步长的内存块儿,也不知道依照何种方式进行分配!
        void * vp = &num;//合法->Win平台(32/64)编译器明白指针所应使用的内存字节尺寸-->不须要明白解析方式-->由于仅仅是一个数值意义的地址
        vp = &db;//空类型的指针能够存储不论什么类型变量(普通变量,一级指针变量,二级指针变量,三级指针变量,多级指针变量等等...)的地址,由于编译器决定了地址存储尺寸
        //printf("%d 
    ", *vp);//:error C2100:非法的间接寻址(问题原因一般是採用空类型的指针对该指针所存储的地址进行解析)->既不明白解析尺寸,也不明白解析方式,所以出错
        //空类型的指针既不能够间接取值,也不能够间接赋值(也就是仅仅能存储内存地址,而不能依据内存地址进行间接訪问操作)
        //*vp = 10;
        printf("%f 
    ", *((double *)vp));//将空类型的指针转化为具体指针类型,然后就达到了既明白了指针的解析步长,也明白了解析方式
    
        system("pause");
    }
    ///02.空指针.c
    #include <stdio.h>
    #include <stdlib.h>
    
    //01.结构体变量:
    //  用于组织多种不同类型的变量
    struct MyStruct//包括四根指针,花心的妹子,能够进行动态的扩充
    {//一个由多个一级指针变量所构成的单个普通结构体变量
        int *p1;
        int *p2;
        int *p3;
        int *p4;
    };
    
    //02.空指针(NULL):
    //  实质:(void *)0
    //  作用:标识不论什么指针变量没有存储内存地址
    //  特点:空指针所指向的内存实体不同意訪问,否则出现訪问异常
    int main02(void)
    {
        //标记指针变量是否存储内存地址
        double db = 10.9;
        double 刘海华 = 10.9;
        double * pDb = NULL;//空指针(NULL):标识不论什么指针变量没有存储内存地址
        while (NULL == pDb)
        {
            //炮之
            pDb = &刘海华;
        }
        *pDb = 1;//空指针所指向的内存实体不同意进行操作
    
        system("pause");
    }

    程序片段(04):01.指针的声明.c
    内容概要:指针的声明

    #include <stdio.h>
    #include <stdlib.h>
    
    //01.声明指针变量:
    //  数据类型+指针级数+指针变量
    int main01(void)
    {
        int * p1;
        int * p2;
    
        system("pause");
    }
    
    //02.特殊声明格式:
    //  格式:数据类型 * p, num;
    //  特点:p是指针变量,num是普通变量
    int main02(void)
    {
        int numA, numB, numC;
        double * pNumA, pNumB, pNumC;
        printf("%d 
    ", sizeof(pNumA));//在Win32平台之下,全部类型,所以级数的指针变量都占用4个字节的内存尺寸
        printf("%d 
    ", sizeof(pNumB));
    
        system("pause");
    }
    
    //03.宏定义(宏替换)和别名定义的差别:
    //  宏定义:第二整块儿替换后置
    //  别名定义:最后整块儿替换前置
    #define 整数  int
    typedef int INT;
    int main03(void)
    {
        整数 x = 3;//替换后置
        INT y = 3;//替换前置
        printf("%d, %d 
    ", x, y);
    
        system("pause");
    }
    
    //04.别名定义规律:
    //  变量定义:int * pNum
    //  添关键字:typedef int * pNum;
    //      特点:变量名变为类型别名
    #define 指针 double *
    typedef double * DBP;
    int main04(void)
    {
        指针 p1;
        DBP p2;
        //printf("%p, %p 
    ", p1, p2);
        printf("%d, %d 
    ", sizeof(p1), sizeof(p2));
    
        system("pause");
    }
    
    //05.特别注意:
    //  1.宏定义(宏替换)和别名定义之间的差别
    //  2.预编译与真实别名
    int main05(void)
    {
        指针 p1, p2;//实质:double *p1, p2, p3;//4,8
        p1 = 0x123;
        p2 = 0x123;
        DBP p3, p4;//doube *类型
        p3 = 0x123;
        p4 = 0x123;
        printf("%d, %d 
    ", sizeof(p1), sizeof(p2));
        printf("%d, %d 
    ", sizeof(p3), sizeof(p4));
    
        system("pause");
    }

    程序片段(05):01.银行.c+02.指针数组.c
    内容概要:数据地址映射

    ///01.银行.c
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    
    //01.C语言编译器特点:
    //  未初始化的普通变量->编译通过
    //  未初始化的指针变量->编译只是
    //02.数据地址映射使用:
    //  1.不同意改变原始内存实体的情况,实现排序
    //  2.比較数据实体,交换指针变量
    //  注:
    //      1.仅仅有整型数据才干使用位运算
    //      2.升序的反面成立,既须要进行交换
    int main01(void)
    {
        int num1;//内存实体
        int num2;
        scanf("%d%d", &num1, &num2);//从从小到大
        int * p1 = &num1;//映射指针
        int * p2 = &num2;
        if (*p1 > *p2)//升序的反面成立,就须要进行交换
        {
            //p1 = p1 ^p2;//仅仅有整型才干使用位运算
            int * ptemp = p1;
            p1 = p2;
            p2 = ptemp;
        }
        printf("%d, %d 
    ", *p1, *p2);
    
        system("pause");
    }
    
    //03.指针变量声明与const关键字使用:
    //  规律:const在指针变量名称前面,也就是星号("*")的右边
    //      就表明该指针变量本身是一个伪常量,也就是该指针变量
    //      不能直接进行改动,可是能够通过间接方式进行改动
    //  特点:const int * p<=>int const * p
    //      仅仅须要关注const与星号("*")之间的相对位置
    //  用处:限定訪问权限
    //      读取权限和改动权限的综合配对
    //void accessControl(const int * p);
    void accessControl(int const * p)//报表权限:限定訪问权限,间接操作的内存实体仅仅能读取,不能进行改动
    {//const在指针其中所能起到的作用
        p = NULL;//通过指针变量间接訪问的内存实体是个真常量,不同意进行间接改动,可是当前指针变量能够进行改动
        printf("*p = %d 
    ", *p);//不能依据空指针进行内存实体訪问,既不能读取也不能写入(操作系统规定)-->编译不报错,可是执行报错
        //*p = 10;//编译报错
    }
    
    int main02(void)
    {
        int num = 100;
        int * pNum = &num;
        accessControl(pNum);
        printf("num = %d 
    ", num);
    
        system("pause");
    }
    ///02.指针数组.c
    #include <stdio.h>
    #include <stdlib.h>
    
    //int a[8];
    //const int *p[8];
    int a[8] = { 1,8,2,7,3,6,4,5 };//int类型的数组 
    const int * p[8] = { &a[0],&a[1],&a[2],a + 3,a + 4,a + 5,a + 6,a + 7 };//指针数组
    void main()
    {
        printf("原来的数组数据:
    ");
        for (int i = 0; i < 8; i++)
        {
            printf("%d
    ", a[i]);
        }
        printf("原来的指针数组指向数据:
    ");
        for (int i = 0; i < 8; i++)
        {
            printf("%d
    ", *p[i]);
        }
    
        for (int i = 0; i < 8 - 1; i++)//最后一个数据不须要冒泡
        {
            for (int j = 0; j < 8 - 1 - i; j++)//冒泡数与与i形成相应关系
            {
                //指针数组其中存储的是指针,然后通过指针进行数据的获取,通过比較指针所相应的数据,然后进行数据交换
                if (*p[j]>*p[j+1])//这里使用指针数组进行比較数据,用数组指针进行数据获取比較,然后进行数据交换 
                {//指针交换
                    int *ptemp = p[j];
                    p[j] = p[j + 1];
                    p[j + 1] = ptemp;
                }
            }
        }
    
        printf("数组数据:
    ");
        for (int i = 0; i < 8; i++)
        {
            printf("%d
    ", a[i]);
        }
        printf("指针数组指向数据:
    ");
        for (int i = 0; i < 8; i++)
        {
            printf("%d
    ", *p[i]);
        }
    
        system("pause");
    }

    程序片段(06):01.输入指针.c
    内容概要:地址输入

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    
    int main01(void)
    {
        int num = 10;
        int data = 20;
        printf("%p, %p 
    ", &num, &data);
        int * pNum = &pNum;
        //对指针变量进行手动地址输入:
        //  格式:scanf("%p", &pNum);
        //  特点:不须要携带0x前缀,并且必须是大写英文字母
        scanf("%p", pNum);//地址类型数组须要使用%p这种输入格式控制符+指针变量的地址
        *pNum = 20 + 3;//操作系统所使用的地址,胡乱进行訪问的时候easy出现系统问题
        printf("num = %d, data = %d 
    ", num, data);
    
        system("pause");
    }

    程序片段(07):01.Screen.c
    内容概要:屏幕输出图片

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    
    int main(void)
    {
        int i = 0;
        while (1)
        {
            HWND win = GetDesktopWindow();
            HDC winDc = GetWindowDC(win);//获取指定窗体的输出接口
            HDC memDc = CreateCompatibleDC(0);//获取内存存储的操作接口
            HBITMAP bitMap = (HBITMAP)LoadImage(win, TEXT("1.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
            SelectObject(memDc, bitMap);//选定图形图像设备-->设置显示什么
            BitBlt(winDc, 0, 0, i++, i++, memDc, i++, i++, SRCCOPY);
            Sleep(100);//模拟0.1秒
            ++i;
            if (3 == i)//到达3次
            {
                i = 0;//重置0次
            }
        }
    
        system("pause");
    }

    程序片段(08):test.c
    内容概要:Test1

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define EN 1024
    int flag = 0;
    char * filePath = "E:\Resource\TestData\BigDB\Test.txt";
    
    //数组赋值
    int intArr[EN];
    void initArr(int intArr[EN])
    {
        //time_t te;
        //unsigned int seed = (unsigned int)(time(&te));
        //srand(seed);
        srand((unsigned int)(time(NULL)));
        for (int i = 0; i < EN; ++i)
        {
            intArr[i] = rand() % EN + 1;
        }
    }
    
    //数组显示
    void showArr(int intArr[EN])
    {
        for (int i = 0; i < EN; ++i)
        {
            printf("%4d 
    ", intArr[i]);
        }
    }
    
    //冒泡排序
    void bubbleSortArr(int intArr[EN])
    {
        for (int i = 0; i < EN - 1; ++i)
        {
            for (int j = 0; j < EN - 1 - i; ++j)
            {
                if (intArr[j] > intArr[j + 1])
                {
                    intArr[j] = intArr[j] ^ intArr[j + 1];
                    intArr[j + 1] = intArr[j] ^ intArr[j + 1];
                    intArr[j] = intArr[j] ^ intArr[j + 1];
                }
            }
        }
    }
    
    //选择排序
    void selectSortArr(int intArr[EN])
    {
        int minIndex = 0;
        int minNum = 0;
        for (int i = 0; i < EN - 1; ++i)
        {
            minIndex = i;
            minNum = intArr[i];
            for (int j = i + 1; j < EN; ++j)
            {
                if (minNum > intArr[j])
                {
                    minIndex = j;
                    minNum = intArr[j];
                }
            }
            if (i != minIndex)
            {
                intArr[i] = intArr[i] ^ intArr[minIndex];
                intArr[minIndex] = intArr[i] ^ intArr[minIndex];
                intArr[i] = intArr[i] ^ intArr[minIndex];
            }
        }
    }
    
    //插入排序
    void insertSortArr(int intArr[EN])
    {
        int currentIndex = 0;
        int currentValue = 0;
        for (int i = 1; i < EN; ++i)
        {
            currentIndex = i;
            currentValue = intArr[currentIndex];
            while (0 < currentIndex && intArr[currentIndex - 1] > currentValue)
            {
                intArr[currentIndex] = intArr[currentIndex - 1];
                --currentIndex;
            }
            intArr[currentIndex] = currentValue;
        }
    }
    
    //二分查找
    int binarySearch(int intArr[EN], int value)
    {
        int minIndex = 0;
        int midIndex = 0;
        int maxIndex = EN - 1;
        while (minIndex <= maxIndex)
        {
            midIndex = (minIndex + maxIndex) / 2;
            if (value == intArr[midIndex])
            {
                return midIndex;
            }
            else if (value < intArr[midIndex])
            {
                maxIndex = midIndex - 1;
            }
            else
            {
                minIndex = midIndex + 1;
            }
        }
        return -1;
    }
    
    //拉格朗日查找
    int lagrangeSearch(int intArr[EN], int value)
    {
        int minIndex = 0;
        int ratioIndex = 0;
        int maxIndex = EN - 1;
        while (minIndex <= maxIndex)
        {
            //midIndex = minIndex + (maxIndex - minIndex) / 2;
            ratioIndex = minIndex + (maxIndex - minIndex)*(value - intArr[minIndex]) / (intArr[maxIndex] - intArr[minIndex]);
            if (value == intArr[ratioIndex])
            {
                return ratioIndex;
            }
            else if (value < intArr[ratioIndex])
            {
                maxIndex = ratioIndex - 1;
            }
            else
            {
                minIndex = ratioIndex + 1;
            }
        }
        return -1;
    }
    
    int main01(void)
    {
        initArr(intArr);
        showArr(intArr);
    
        insertSortArr(intArr);
        printf("binSearch Index = %d 
    ", binarySearch(intArr, 880));
        printf("lagrangeSearch index = %d 
    ", lagrangeSearch(intArr, 880));
    
        system("pause");
    }
  • 相关阅读:
    loj#6433. 「PKUSC2018」最大前缀和(状压dp)
    PKUWC2019游记
    10. Regular Expression Matching
    9. Palindrome Number
    8. String to Integer (atoi)
    7. Reverse Integer
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    4. Median of Two Sorted Arrays
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8341899.html
Copyright © 2011-2022 走看看