当前位置: 首页 > 文档资料 > C 语言程序设计 >

玩转多级指针

优质
小牛编辑
144浏览
2023-12-01

二级指针

#include <stdio.h>
#include <stdlib.h>

//01.指针变量规律:
//  1.指针变量必须注意指针的类型
//  2.指针变量必须注意指针所指向实体的类型
//  3.针对于指针变量的(加减一个整数)规律:
//      实质:必须根据指针变量所存储的指针所指向的实体类型来定断
//      形式:p+1<=>p+sizeof(*p);-->必需带上内存实体才能准确!
//  4.指着变量的级数规律:
//      (1).如何表明当前指针变量存储的是什么类型的变量的地址?
//          double **pp-->二级指针变量PP存储的是(double * p)这个一级指针变量的地址
//          规律:指针变量的声明级数减去一级就是该指针变量所存储的变量的地址
//      (2).如何确定取值运算符(星号:"*")当前所访问的内存实体是什么?
//          double **pp-->**pp-->(指针变量声明级数-当前取值运算符操作的级数)
//              就是该取值运算符所访问的变量的数据
//          例如:**-**=0-->变量的数据
int main01(void)
{
    double db = 10.8;
    double * p = &db;
    //double * pT = &p;//指针类型不匹配
    double ** pp = &p;
    //printf("%p, %p \n", pT, pT + 1);//PT结果不正确
    printf("%p, %p \n", pp, pp + 1);
    printf("%lf \n", **pp);//普通变量

    system("pause");
}

int a = 10;
int b = 20;
//02.函数形参的副本机制要点:
//  只是针对于数组类型没有副本机制,其他所有类型的形参都有副本机制
//  原理:就是将数组类型进行退化为指针("指向数组元素的指针"),以避免副本机制产生
//  注:指向数组元素的指针,明确该数组当中所存储的到底是什么类型的数据!
void changeP(int * p)//指针变量也有副本机制
{
    printf("change: &p = %p \n", &p);
    p = &b;
}

void changePP(int ** pp)
{
    *pp = &b;
}

//03.要想让被掉函数修改主调函数当中的变量数据:
//  诀窍:至少必须传递主调函数当中的变量地址(至少得是直接地址)
int main02(void)
{
    int * p = &a;
    printf("main: &p = %p \n", &p);
    printf("%d \n", *p);//10
    //p = &b;
    //changeP(p);
    changePP(&p);
    printf("%d \n", *p);

    system("pause");
}

//04.集团体系架构关系:
//  职称体系可以通过指针级数进行描述
//  例如:司令采用的是10级指针描述,里面存储的军长的地址
int main03(void)
{
    int a = 10;
    int * p = &a;
    int ** pp = &p;
    int *** ppp = &pp;
    printf("%p \n", &ppp);
    //集团体系架构关系可以通过指针级数进行描述

    system("pause");
}

//05.字符类型的指针如果指向的是代码区符号表实体:
//  那是不允许通过字符指针间接修改代码区符号表内容的!
//  注:代码区符号表的内容只能够进行读取操作,不能进行写入操作
int main04(void)
{
    char * p = "123";//"123"存储于代码区符号表
    *p = 'A';//*p所访问的内存实体位于代码区符号表,因此不能直接进行修改
    printf("%p \n", p);

    system("pause");
}

void run(char * arr[5])
{
    printf("run: sizeof(arr) = %d \n", sizeof(arr));//sizeof(char **)
    for (int i = 0; i < 5; ++i)
    {
        system(arr[i]);
    }
}

//06.数组作为形参究竟退化为什么类型的指针?
//  实质:退化为指向该数组当中所有元素的指针!
//int arr[5]-->arr作形参,退化为-->int * arr
//char * arr[5]-->arr作形参,退化为-->char ** arr
void runT(char **arr)//指针数组作为形参,将会退化成为二级指针
{
    printf("runT: sizeof(arr) = %d \n", sizeof(arr));
    for (int i = 0; i < 5; ++i)
    {
        system(arr[i]);//arr[i]的实质其实是一级指针
    }
}

//07.数组作为形参的时候,会具体转化为指向该数组当中每个元素的指针类型:
//  在访问的时候,采取该指针类型变量名加上中括号("[]")等同于数组访问方式!
//  实质:arr[i]<=>*(arr+i)-->效果等价
int main05(void)
{
    //int arr[10];
    char * arr[5] = { "calc", "notepad", "mspaint", "tasklist", "pause" };
    printf("main: sizeof(arr) = %d \n", sizeof(arr));//诀窍:sizeof(varName)<=>sizeof(*&varName)
    run(arr);
    //runT(arr);

    system("pause");
}

玩转多级指针

char **getMem51(int num)
{
    int i = 0;
    char **p2 = NULL;
    p2 = (char **)malloc(sizeof(char *) * num);
    if (p2 == NULL)
    {
        return NULL;
    }

    for (i=0; i<num; i++)
    {
        p2[i] = (char *)malloc(sizeof(char)  * 100  ); //char buf[100];
        sprintf(p2[i], "%d%d%d", i+1, i+1, i+1);
    }
    return p2;
}

int getMem52(char ***p3 , int num)
{
    int i = 0;
    char **tmp = NULL;

    if (p3 == NULL)
    {
        return -1;
    }

    tmp = (char **)malloc(sizeof(char *) * num);
    if (tmp == NULL)
    {
        return NULL;
    }

    for (i=0; i<num; i++)
    {
        tmp[i] = (char *)malloc(sizeof(char)  * 100  ); //char buf[100];
        sprintf(tmp[i], "%d%d%d", i+1, i+1, i+1);
    }
    *p3 = tmp; 
    return 0;
}

void getMem52_Free(char ***p3 , int num)
{
    int i = 0;
    char **tmp = NULL;

    if (p3 == NULL)
    {
        return ;
    }
    tmp = *p3; 

    for (i=0; i<num; i++)
    {
        free(tmp[i]);
    }
    free(tmp);

    *p3 = NULL; //把实参赋值成null
}

void main66()
{
    int i = 0, j = 0;
    char **p2 = NULL;
    int num = 5;
    char *tmp = NULL;
    char tmpbuf[100];
    //p2 = getMem51(num);

    getMem52(&p2, num);

    for (i=0; i<num; i++)
    {
        printf("%s \n", p2[i]);
    }

    getMem52_Free(&p2, num);
    printf("hello...\n");
    system("pause");
    return ;
}