玩转多级指针
优质
小牛编辑
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 ;
}