C语言指针总结
C语言指针总结
要时刻牢记内存四区模型和C语言的函数副本机制
一、概述
数据类型本质上是:固定内存大小的别名。其中作用是编译器根据数据类型为变量(对象)分配内存空间。
指针是一种数据类型,其变量占用4个自己的内存空间。指针变量存放的是地址
内存四区:堆区、栈区、全局区、代码区
注意:
要区别指针变量和指针变量所指向的内存块
指针的数据类型是它所指向的内存空间的数据类型
指针的步长(p++)由它所指向的内存空间类型来决定
例:
int a[5]; char c[5];
int *ap=a;
char *cp=c;
ap++;//步长为4个字节
cp++;//步长为1个字节
二、指针的意义
利用指针可以实现间接赋值。通常利用函数来改变函数外部的变量。
三、一级指针
1.做函数参数---间接修改普通变量
1 void setmem(int *p)
2 {
3 *p=100;
4 }
5
6 void main()
7 {
8 int n=10;
9 int *p=&n;
10
11 *p=20;//--间接修改普通变量
12
13 setmem(p);//--间接修改普通变量
14 }
2、做输入
1 int showList(char *str)
2 {
3 if(str==NULL)
4 return 0;
5 printf("%s\n",str);
6 return 1;
7 }
8 void main()
9 {
10 char *str="main3 hello world!";
11 if(showList(str)==0)
12 printf("error!\n");
13 }
3、做输出
void setmem(int *p)
{
*p=100;
}
例:
1 int getLen(char *str /*in*/,int *len/*out*/)
2 {
3 if(str==NULL)
4 return 0;
5 *len=strlen(str);
6 return 1;
7 }
8
9 void main()
10 {
11 int len=0;
12 char *str="hello world!";
13 if(getLen(str,&len)==0)
14 printf("error!\n");
15
16 printf("str=%s\n",str);
17 printf("str length is:%d\n",len);
18
19 system("pause");
20 }
注:一级指针做函数参数的输出模型本质上是间接修改指针所指向的变量
想要通过函数修改一级指针的指向,就要用到二级指针,这与函数参数的副本机制有关
四、二级指针
1.做函数参数---间接修改一级指针变量
1 void getm3(char **p)
2 {
3 char *tmp;
4 tmp=(char *)malloc(sizeof(char)*20); //--与数组对比理解
5 strcpy(tmp,"hello world!");
6 *p=tmp;
7 }
8
9 void main()
10 {
11 char *str="hahaha";
12 printf("%s\n",str);
13 getm3(&str);
14 printf("%s\n",str);
15 if(str!=NULL)
16 {
17 free(str);
18 str=NULL;
19 }
20 }
注:要想在函数内修改一级指针的指向,就要将二级指针作为函数的参数,通过二级指针间接修改一级指针的指向
2.做输出
1 void getm3(char **p)
2 {
3 char *tmp;
4 tmp=(char *)malloc(sizeof(char)*20);
5 strcpy(tmp,"hello world!");
6 *p=tmp;
7 }
五、指针与数组
(1)指针与一维数组
1、基本概念
char a[50]="hello wold!";
char *p=a;
a[i]====>*(p+i) &a[i]====>p+i====>a+1
注:a 是数组首元素的地址,a+1的步长是1个字节
&a 是整个数组的地址,&a+1的步长是50个字节
2、自定义数组数据类型
typedef int (ArrayType)[10];
ArrayType array; //===>int array[10];
3、指针数组与数组指针
定义指针数组:----用来存放地址的数组
char *Myarray[]={"111","222","333333"};
定义数组指针:----用一个指针来指向数组
A:
1 typedef int (ArrayType)[10]; 2 void main() 3 { 4 int i; 5 int myArray[10]; //--相当于一级指针 6 ArrayType *pArray; 7 pArray=&myArray;//---相当于二级指针 8 9 for(i=0;i<10;i++) 10 { 11 (*pArray)[i]=i+1; 12 } 13 14 }
B:
typedef int (*ArrayType)[10];
ArrayType pArray;
int myArray[10];
pArray=&myArray;
C:
int (*pArray)[10];
int myArray[10];
pArray=&myArray;
4、做函数参数
一维数组做函数参数会退化为一级指针。
(2)指针与二维数组
1、基本概念
int a[3][5];
a+1 步长为4*5 字节
&a+1 步长为3*(4*5)字节
(a+i) 二级指针--代表第i行的地址
*(a+i) 一级指针--第i行首元素的地址
*(a+i)+j 一级指针--第i行第j列元素的地址等价于 &a[i][j]
*(*(a+i)+j)--第i行第j列元素等价于 a[i][j]
2、数组指针--指向数组的指针
1 int a[3][5]; 2 int (*pArray)[5]; 3 pArray=a; 4 for (i=0; i<3; i++) 5 { 6 for (j=0; j<5; j++) 7 { 8 pArray[i][j]=i+j; 9 } 10 }
3、做函数参数
void printArray01(int a[3][5])
void printArray01(int a[][5])
void printArray03( int (*b)[5])
注:
数组参数 等效的指针参数
一维数组 char a[30] 指针 char*
指针数组 char *a[30] 指针的指针 char **a
二维数组 char a[10][30] 数组的指针 char(*a)[30]
(3)指针数组的应用---待续
六、指针与结构体
1、基本知识
1 typedef struct student{ 2 3 char name[10]; 4 int age; 5 6 }student; 7 8 student stu1={"abcde",23}; //分配内存 9 student *p=NULL; 10 *p = &stu1; 11 12 stu1.age=30; // "."运算符 是寻址操作。用来计算age相对于stu1 的偏移量,在cpu中计算,不操作内存 13 p->.age=28; // "->"运算符 是寻址操作。用来计算age相对于stu1 的偏移量,在cpu中计算,不操作内存 14 15 student stu2; 16 stu2=stu1; // 编译器允许相同类型结构体之间的赋值
2、结构体做函数参数
1 void printfStu(student stu) 2 { 3 printf("stu.name=%s , sut.age=%d\n",stu.name,stu.age); 4 }
3、结构体指针做函数参数
A:
1 void printfStu2(student *stu) //普通结构体变量的地址做参数 2 { 3 printf("stu.name=%s , sut.age=%d\n",stu->name,stu->age); 4 }
B:
1 int printStudent(student * stu,int num) //结构体数组做参数 2 { 3 int i=0; 4 if(stu==NULL) 5 return 0; 6 for(i=0;i<num;i++) 7 { 8 printf("name=%s,age=%d\n",stu[i].name,stu[i].age); 9 } 10 11 return 1; 12 }
C:
1 student * createStudent01(int num) //返回结构体指针类型 2 { 3 student * temp; 4 temp=(student *)malloc(sizeof(student)*num); 5 if(temp==NULL) 6 { 7 return NULL; 8 } 9 10 return temp; 11 12 }
D:
1 int createStudent02(student **p, int num)//二级结构体指针做参数,用来修改一级指针的指向 2 { 3 int i = 0; 4 student * tmp = NULL; 5 tmp = student *)malloc(sizeofstudent * num); 6 if (tmp == NULL) 7 { 8 return -1; 9 } 10 11 *p = tmp; //二级指针 形参 去间接的修改 实参 的值 12 13 return 0; 14 }