• C++ 结构体指针理解


    上一篇基础链接 https://www.cnblogs.com/xuexidememeda/p/12283845.html

    主要说一下链表里面双重指针

    先说一下结构体

    typedef struct LNode
    {
    	int data;
    	struct LNode *next;
    
    }LNode, *LinkList;
    
    typedef 把这个结构体定义一个别的名字 
    LNode==LNode 类型     LinkList==LNode* 类型 *LinkList 是函数指针..........这个写法我也很懵逼没法从内存角度理解 最后也有简单介绍函数指针
    你不定义typedef一样直接可以用LNode 就是写的时候不方便 但是我觉得对新手易于理解

      


    先上总代码 两个main12是测试函数 自己改着玩

    // ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
    //
    #include "stdafx.h"
    #include<malloc.h>
    using namespace std;
    
    typedef struct LNode
    {
        int data;
        struct LNode *next;
    
    }LNode, *LinkList;
    
    
    //--------------后插法创建单链表 ------------------
    void CreateList_E(LinkList &head, int n)
    {
        int i;
        LinkList pnew;
        LinkList pend;//定义最后的节点指针; 
        //先建立头结点,数据为空;
        
        head = new LNode;
        head->next = NULL;
        pend = head;//头结点是最后的节点 ;
        for (i = 0; i < n; i++)
        {
            pnew = new LNode;
            printf("请输入第%d个节点的数据:
    ",i);
            scanf_s("%d", &pnew->data);
            pnew->next = NULL;
            pend->next = pnew;
            pend = pnew;
    
        }
    }
    
    void CreateList_E1(LNode* &head, int n)
    {
        int i;
        LinkList* ptr;
        LinkList pnew;
        LinkList pend;//定义最后的节点指针; 
        //先建立头结点,数据为空;
    
        head = new LNode;  //返回的是分配空间的首地址LNode* 类型
        head->next = NULL;
        pend = head;//头结点是最后的节点 ;
        for (i = 0; i < n; i++)
        {
            pnew = new LNode;
            printf("请输入第%d个节点的数据:
    ", i);
            scanf_s("%d", &pnew->data);
            pnew->next = NULL;
            pend->next = pnew;
            pend = pnew;
        }
    
    }
    //双重指针 头结点貌似必须在外面创建??
    void CreateList_E1(LNode** lnode, int n)
    {
        LinkList head = *lnode;
        head->next = NULL;
    
        for (int i = 0; i < n; i++)
        {
            LNode* pnew = new LNode;
            printf("请输入第%d个节点的数据:
    ", i);
            scanf_s("%d", &pnew->data);
            pnew->next = head->next;
            head->next = pnew;
        }
    
    
        
    
    
        
    
    }
    
    
    
    //------------------打印链表---------------- 
    void PrintList(LinkList head)
    {
        LinkList item;
        item = head;
        item = item->next;//这一步不是必须要做的,为了跳过头结点(没有数据) 
        while (item != NULL)
        {
            printf("----%d----
    ", item->data);
            item = item->next;
    
        }
    }
    void main1()
    {
    
        LNode*  L = NULL;
        int n;
        printf("输入要创建的链表结点个数:
    ");
        scanf_s("%d", &n);
        CreateList_E1(L, n);
        printf("
    打印结果!
    ");
        PrintList(L);
    
    }
    
    void main2()
    { 
        LNode* temp= new LNode;
        LNode**  L= &temp;
        int n;
        printf("输入要创建的链表结点个数:
    ");
        scanf_s("%d", &n);
        CreateList_E1(L,n);
        printf("
    打印结果!
    ");
        PrintList(*L);
    
    
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        //main1();
        main2();
    }
    View Code

    说一下创建+赋值链表函数(自己看着前面的看)

    void CreateList_E(LinkList &head, int n)==void CreateList_E1(LNode* &head, int n)

    LinkList 的类型其实是LNode* 类型 然后&head 是传参引用?好像是这样的(忘怎么说了)  如果你不带&符号只能在本函数打印出来赋值语句 在封装的函数是无法打印的

    跟你的swap学过一个函数交换值他真实的值还是不变,多数人疑问就是我传的可是一个指针类型,他是一个地址呀!为什么还是传不过去呢 因为你的指针地址是在栈中分配空间用完就销毁呢( CreateLis函数运行结束main函数无法找到原来分配的地址)    只要头结点是在main函数中分配的那么他以后的指针在哪分配都没问题的..... 看似简单的一个问题,要 真正弄懂其实要看编译器怎么办的就是看汇编

    (本人汇编基础不扎实自学的以后博客再补上!!)

    唯一确定的是不加&函数call return 之后会 main函数无法得到指针的地址

    void CreateList_E1(LNode** lnode, int n)   这个和CreateList_E(LinkList &head, int n) 差不多因为我们之前说过 加一个& 相当于类型后加个*


    其实你完全可以想简单点你完全可以把指针类型当成类似int之类的类型 ,比如  要实现 void swap1(int a, int b)交换a b的值  我们都知道无法交换值  要交换值有两种方法 一种是void swap1(int* a, int* b)  一种是引用   所以要使用指针的指针


     函数指针...............简单例子

    例如:

    class Test
    {
    private:
    int x;
    int y;
    public:
    Test(){    x = 1;    y = 2;}
    void Pintf() { cout << x << " " << y << endl; }
    };
    int _tmain(int argc, _TCHAR* argv[])
    {
        Test a;
        a.Pintf();
        int* b = (int*)&a;
        //cout << *b;
        cout << &a << endl;  //如果直接输出a的内存的话 是0001 0002 //没法直接输出必须用指针查看值
    
        short* c = (short*)&a;
        char* d = (char*)&a;
        cout << *d << endl;
        cout << *c<<endl;
        cout <<b;
        getchar();
    
        /*
        
        17:     Test a;   
        00972CC8 8D 4D F0             lea         ecx,[a]                      ecx 0x0108FCB0  this 指针
        00972CCB E8 E5 E7 FF FF       call        Test::Test (09714B5h)
        18:     a.Pintf();
        00972CD0 8D 4D F0             lea         ecx,[a]
        00972CD3 E8 7A E6 FF FF       call        Test::Pintf (0971352h)
        19:     int* b = (int*)&a;
        00972CD8 8D 45 F0             lea         eax,[a]
        00972CDB 89 45 E4             mov         dword ptr [b],eax
        20:     //cout << *b;
        21:     cout << &a<<endl;
        00972CDE 8B F4                mov         esi,esp
        00972CE0 68 ED 13 97 00       push        9713EDh
        00972CE5 8B FC                mov         edi,esp
        00972CE7 8D 45 F0             lea         eax,[a]
        00972CEA 50                   push        eax
        00972CEB 8B 0D F8 10 98 00    mov         ecx,dword ptr ds:[9810F8h]
        00972CF1 FF 15 FC 10 98 00    call        dword ptr ds:[9810FCh]
        00972CF7 3B FC                cmp         edi,esp
        00972CF9 E8 40 E6 FF FF       call        __RTC_CheckEsp (097133Eh)
        00972CFE 8B C8                mov         ecx,eax
        00972D00 FF 15 9C 10 98 00    call        dword ptr ds:[98109Ch]
        00972D06 3B F4                cmp         esi,esp
        00972D08 E8 31 E6 FF FF       call        __RTC_CheckEsp (097133Eh)
        
        
        */
    
    }
    Test a; 这个a 到底是什么? 其实就是这个类的开头 比如这个开头存的就是0001 0002 x,y  我原来认为a存的 一直是一个地址指向 00010002这位置
    假如test 类里面有虚函数 例如 virtual void Function_4() 则 Test a 中 a的首地址开头存的就是一个虚表函数 总地址例如是A (意思是 *A 是你第一个虚函数 *(A+1)是你第二个虚函数)
    如果你多继承而且父类中有虚函数则比如有2个则有2个虚表
  • 相关阅读:
    HWOJ之纠结的优化
    java中的对象数组
    短路特性的运用
    归并排序
    两个有序数列的合并
    java中的注释规范
    堆排序
    堆的建立
    希尔排序
    直接插入排序
  • 原文地址:https://www.cnblogs.com/xuexidememeda/p/12292480.html
Copyright © 2020-2023  润新知