欢迎大家来到IT世界,在知识的湖畔探索吧!
指针变量能够构建变量之间的联系,特别是用做链式存储和函数传址时。
理解指针变量的关键在于理解指针变量的己型、他型,己址、他址,己值、他值。
通过函数的传值和传址(地址是一个指针变量的值),可以更改指针变量的己值和他值。改变己值时直接使用指针变量名,改变他值(也就是指针变量指向的地址对应的值)需要解引用。
函数不能传递一个数组,但可以传递数组指针。数组名在用做实参的上下文中指向数组首元素的指针变量的语义。这个指向数组的指针变量的解引用是对数组元素的操作。
1 一级指针变量的己值、他值及通过函数传引用的副作用来修改
#include <stdio.h>
#include <stdlib.h>
void funcP(int *p,int **pp)
{
*p = 3; // 主调函数main通过被调函数funcP改变他值(要解引用,引用语义,地址指向)
int t = 0; // 被调函数的局部变量
p = &t; // p指向局部变量,p没有解引用,改变己值,与主调函数无关(值语义,副本机制)
*pp = (int *)malloc(sizeof(int)); // 解引用,引用语义,更改的是主调函数一个指针的值
**pp = 4;
}
int main()
{
int a = 0;
int b = 1;
int *pa = &a; // a通过&a被取址后,可以通过pa来修改
int *pb = &b;
pa = pb; // 一级指针改变己值
*pa = 2; // 一级指针改变他值,需要解引用
printf("%d %d\n",b,*pa); // 2 2
// 通过函数尝试改变己值和他值
funcP(pa,&pa); //使用&表示修改自身,因为取的是自己的地址,没有&的pa表示修改的是其值&a
printf("%d %d\n",b,*pa); // 3 4
free(pa);
getchar();
return 0;
}
欢迎大家来到IT世界,在知识的湖畔探索吧!
2 二级指针变量的己值、他值及通过函数传引用的副作用来修改
欢迎大家来到IT世界,在知识的湖畔探索吧!#include <stdio.h>
#include <stdlib.h>
void funcP(int **pp,int ***ppp)
{
*pp = (int *)malloc(sizeof(int));// 主调函数main通过被调函数funcP改变他值(要解引用,引用语义,地址指向)
**pp = 3; // 此时是改变动态内存了
int t = 0; // 被调函数的局部变量
int *pt = &t;
pp = &pt; // pp指向局部变量,p没有解引用,改变己值,与主调函数无关(值语义,副本机制)
*ppp = (int **)malloc(sizeof(int*)); // 解引用,引用语义,更改的是主调函数一个指针的值
**ppp = (int*)malloc(sizeof(int));
***ppp = 4;
}
int main()
{
int a = 0;
int b = 1;
int *pa = &a;// a取过&被取址后,可以被pa解引用修改
int *pb = &b;
int **ppa = &pa; // pa取过&被取址后,可以被ppa解引用修改
// 以上可见,pa作为,可以修改其指向的值a,也可以被修改,但需要更高一级指针来解引用
int **ppb = &pb;
ppa = ppb; // 二级指针改变己值
*ppa = pb; // 二级指针改变他值,需要解引用
**ppa = 2;
printf("%d %d\n",b,**ppa); // 2 2
// 通过函数尝试改变己值和他值
funcP(ppa,&ppa);//使用&表示修改自身,因为取的是自己的地址,没有&的pa表示修改的是其值&pb
printf("%d %d\n",b,**ppa); // 2 4
free(*ppa);
free(ppa);
getchar();
return 0;
}
3 在链表操作中,可以通过二级指针来创建链表表头
#include <stdio.h>
#include <stdlib.h>
struct Node{
int data;
struct Node* next;
};
void insertList(Node** head,int data)
{
Node* pn = (Node*)malloc(sizeof(Node));
pn->data = data;
if(*head == NULL) // head解引用后,操作的还是一个指针
{
pn->next = *head; // NULL
*head = pn;
}
else
{
pn->next = (*head)->next;
(*head)->next = pn;
}
}
int main()
{
Node * head = NULL;
insertList(&head,2);//使用&给指针取地址值,表示可以修改head自身,而不是其指向。
insertList(&head,3);
printf("%d\n",head->data);
printf("%d\n",head->next->data);
free(head->next);
free(head);
getchar();
return 0;
}
4 指针变量和数组指针变量做函数参数与数组本身与元素
无法传入和返回一个数组或函数,但可以传入和返回一个数组指针或函数指针。
除非返回动态数组,通常,通过函数处理数组本非处理己身的值语言,而是处理数组元素的引用语义,其合量性可以从两方面去理解:
I 指针的算术运算(偏移或移动),以其指向的数据类型的长度为移动的衡量单位,是元素的个数而不是byte数量,所以要求将数组名转换为指向数组首元素的指针变量。
II 函数参数传址,通过指针传递,函数体内解引用才是操作指针指向对象,如果是操作指针本身则不会对其指向产生副作用。对数组的操作可以是数组名的下标操作或其指向指向数组的指针变量的解引用操作。
欢迎大家来到IT世界,在知识的湖畔探索吧!#include <stdio.h>
#include <stdlib.h>
void funcAr(int *p,int size)
{
for(int i=0;i<size;i++)
{
p[i] = i+1; // 解引用(他值操作),也是数组元素的操作
}
p = (int*)malloc(sizeof(int)*size); // 己值操作,没什么意义,还会带来内存泄露
}
void funcArr(int(*prr)[11],int row)
{
for(int i=0;i<row;i++)
for(int j=0;j<11;j++)
*(*(prr+i)+j) = i*j; // 解引用(他值操作)数组元素。
//prr[i][j] = i*j;
prr = (int(*)[11])malloc(sizeof(int)*row*11); // 己值操作,没什么意义,还会带来内存泄露
}
int main()
{
int ar[11] = {0};
funcAr(ar,sizeof ar / sizeof *ar);
printf("\n");
int arr[3][11] = {0};
funcArr(arr,3);
//funcArr(&ar,0); // 虽然编译无误,但无什么意义
getchar();
return 0;
}
5 动态二维数组通过函数来申请
#include <stdio.h>
#include <stdlib.h>
void heapAr(int**p,int n)
{
*p = (int*)malloc(sizeof(int)*n);
}
void heappa(int*(*p)[5],int n,int m)
{
for(int i=0;i<n;i++)
{
(*p)[i] = (int *)malloc(sizeof(int)*m);
}
}
void heapArr(int ***p,int r,int c)
{
*p = (int**)malloc(sizeof(int*)*r);
for(int i=0;i<r;i++)
{
(*p)[i] = (int *)malloc(sizeof(int)*c);
}
}
int main()
{
int i,j;
int *p = NULL;
int n = 5;
heapAr(&p,n);
free(p);
int * pa[5];
heappa(&pa,5,5);
for(i=0;i<5;i++)
for(j=0;j<5;j++)
pa[i][j] = (i+1)*(j+1);
for(i=0;i<5;i++){
for(int j=0;j<5;j++)
printf("%d ",pa[i][j]);
printf("\n");
}
for(i=0;i<5;i++)
free(pa[i]);
int **pp = NULL;
int row = 3;
int col = 5;
printf("请输入需要分配的数组的行和列:");
scanf("%d %d",&row,&col);
heapArr(&pp,row,col);
for(i=0;i<row;i++)
for(j=0;j<col;j++)
pp[i][j] = (i+1)*(j+1);
for(i=0;i<row;i++){
for(int j=0;j<col;j++)
printf("%d ",pp[i][j]);
printf("\n");
}
for(i=0;i<row;i++)
free(pp[i]);
free(pp);
getchar();
getchar();
return 0;
}
-End-
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/50121.html