一、复杂指针定义
1、简单指针 -> 指向基本数据类型 char int long..
复杂指针 -> 指向非基本数据类型 指针/数组/函数/结构体
2、二级指针?
指向指针的指针。
int a;
int *pa = &a; pa就是一级指针
int **p = &pa; p就是二级指针
3、数组指针?
指向整个数组的基地址指针就是“数组指针”
1)如何定义数组指针?
方法与定义简单指针一致。
int a;
int *p = NULL;
p = &a; -> 整型指针 -> 指针类型:int* -> 代表该指针指向一个整型数据。
int A[3];
int(*p)[3] = &A; -> 数组指针 -> 指针类型:int(*)[3] -> 代表该指针指向一个具有3个int类型数据的数组
2)数组中&A与A有什么区别?
&A -> 代表这个数组的地址 int(*)[3]
A -> 代表这个数组首元素的地址 int *
int A[3];
int(*p)[3]=A; -> 不能把int*类型数据赋值给int(*)[3],因为类型不匹配!
3)解引用
int A[3] = {100,200,300};
int(*p)[3] = NULL;
p=&A;
请问*p得到什么?
*p = *(&A) = A = &A[0] -> 解引用数组指针,得到数组首元素的地址。
请问p[0]/p[1]是什么?
p[0] = *(p+0) = *(p) = *(&A) = A = &A[0]
p[1] = *(p+1) p+1已经越界,访问未知区域。
请问(*p)[1]得到什么?
(*p)[1] = (*&A)[1] = A[1] = 200
练习1:若有以下说明:
int B[10];
int (*p)[10]=&B;
int *px=B;
则下列能正确引用数组的元素的是?
A. *p+1 B.*(p[1]) C.(px+3)[2] D.(*px)[3] E. (*p)[0] F. *(px+1)
4、函数指针?
指向函数的一个指针。
1)如何定义函数指针?
例子:
int a;
int *p = &a;
int fun(int x,int y); -> 指向该函数指针怎么写?
int(*p)(int,int) = &fun;
结果:int(*p)(int,int)
变量名:p
数据类型:int(*)(int,int)
2)在linux C语言中,函数名字就是函数的地址,所以: fun 等价于 &fun
int fun(int x,int y);
int(*p)(int,int) = &fun; 等价于 int(*p)(int,int) = fun;
练习2:求出两个数字最大值,要求使用函数指针完成。
#include <stdio.h>
int fun(int x,int y)
{
int z;
z = (x > y ? x : y);
return z;
}
int main()
{
int max;
int(*p)(int,int) = NULL;
p = &fun;
max = p(100,200);
printf("max = %d\n",max);
return 0;
}
二、数组作为函数的参数时,在内存中的变化情况?
1、学习过传递类型
例子1:传递int类型数
void fun(int x) //x = a;
fun(a);
例子2:传递指针地址
void fun(int *x) x = &a;
fun(&a);
例子3:传递函数
void fun(void (*x)(int)) x = &myfun / x = my_fun
void my_fun(int a);
fun(my_fun);
2、数组作为实参时,其实将数组首元素传递过去。
例子:
以下三种写法完全等价
void fun(int x[]) // x = A = &A[0]
void fun(int x[3]) // x = A = &A[0]
void fun(int *x) // x = A = &A[0]
int main()
{
int A[3];
fun(A); //在这里,A不是作用sizeof(),所以代表首元素地址 int*
//等价于fun(&A[0]);
}
练习:
10、有以下程序
void swap1(int c0[], int c1[])
{
int t ;
t=c0[0]; c0[0]=c1[0]; c1[0]=t;
}
void swap2(int *c0, int *c1)
{
int t;
t=*c0; *c0=*c1; *c1=t;
}
main()
{
int a[2]={3,5}, b[2]={3,5};
swap1(a, a+1);
swap2(&b[0], &b[1]);
printf(“%d %d %d %d\n”,a[0],a[1],b[0],b[1]);
}
程序运行后的输出结果是( D )
A)3 5 5 3 B)5 3 3 5
C)3 5 3 5 D)5 3 5 3
9、有以下程序
void fun(int *a,int i,int j)
{
int t;
if(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
fun(a,++i,--j);
}
}
main()
{
int a[]={1,2,3,4,5,6},i;
fun(a,0,5);
for(i=0;i<6;i++)
printf(“%d”,a[i]);
}
执行后的输出结果是( A )
A) 6 5 4 3 2 1 B) 4 3 2 1 5 6
C) 4 5 6 1 2 3 D) 1 2 3 4 5 6
三、数组作为函数的返回值时,情况是如何的?
#include <stdio.h>
char *fun()
{
char A[4] = {‘a‘,‘b‘,‘c‘};
printf("A = %p\n",A);
printf("%s\n",A);
return A; //-> 返回数组首元素的地址 类型: char*
}
int main()
{
char *p = NULL;
p = fun();
printf("p = %p\n",p);
printf("%s\n",p);
}
编译警告:warning: function returns address of local variable -> 数组A再函数fun结束时,内存空间会释放。
解决方案:
1)将数组设置为全局变量
2)在数组前面加static修饰数组 -> 数组被static修饰后,不再存在与栈区,而是存在数据段。
四、二维数组
1、二维数组的基本概念
二维数组在内存中是线性规则,不存在行与列的关系,其实二维数组就是一个一维数组,只是一维数组中每一个成员都是数组。
例子:
整型数组: int A[5] -> 该数组中每一个成员都是int类型数据。
二维数组: 数组 A[5] -> 该数组中每一个成员都是数组
2、如何定义二维数组?
只需要确定数组的元素个数与每一个元素的数据类型即可!
定义数组的方式:
例子1:定义具有5个int类型数据的数组:
1)给一个数组名 A
2)确定数组中元素的个数,使用[]括住它,跟在数组名后面 A[5]
3)确定数组中每一个成员的数据类型是什么 int a;
4)将第3步结果的变量名去掉 int
5)将第4步结果写在第2步结果前面 int A[5]
例子2:定义二维数组
1)给一个数组名 B
2)确定数组中元素的个数,使用[]括住它,跟在数组名后面 B[2]
3)确定数组中每一个成员的数据类型是什么 int A[3]
4)将第3步结果的变量名去掉 int [3]
5) 将第4步结果结合到第2步结果中 int B[2][3]
结果:int B[2][3]
代表这个数组中有两个成员,每一个成员都是具有3个int类型数据的数组。
3、二维数组的赋值
int B[2][3] = {{1,2,3},{4,5,6}};
4、二维数组的数组名
例子:int B[2][3]
sizeof(B) = 24
&B -> 代表整个二维数组的地址, 类型: int(*)[2][3]
B=&B[0] -> 代表二维数组的首元素的地址, 类型: int(*)[3]
B[0]=&B[0][0] -> 代表二维数组的首元素的首元素的地址, 类型: int *
B[0][0] -> 代表二维数组的首元素的首元素的值, 类型: int
5、解引用
1)请问解引用二维数组的名字得到什么?
得到二维数组的首元素的首元素的地址。
int B[2][3] = {{1,2,3},{4,5,6}};
*B=*(&B[0])=B[0]=&B[0][0]
2)请问解引用二维数组的首元素得到什么?
得到二维数组的首元素的首元素的值。
*B[0]=*(&B[0][0])=B[0][0]
练习2:
12、若有以下说明和语句:int c[4][5],(*p)[5];p=c;能正确引用c数组元素的是( D )
A) p+1 B) *(p+3) C) *(p+1)+3 D) *(p[0]+2)
13、有以下程序
main()
{
int a[3][3],*p,i;
p=&a[0][0];
for(i=0;i<9;i++)
p[i]=i+1;
printf(“%d\n”,a[1][2]);
}
程序执行以后的输出结果是( B )
A) 3 B) 6 C) 9 D) 7
原文地址:https://www.cnblogs.com/zjlbk/p/11172159.html