1.二维数组概念:
父子数组:把二维数组回归到一维数组
int a[3][4]={{1,3,5,7};{9,11,13,15};{17,19,21,23}}
a[0]=1,3,5,7 //a[0][0], a[0][1],a[0][2],a[0][3],
a[1]=9,11,13,15
a[2]=17,19,21,23
父数组:二维数组名a,地址
子数组:a[0]/a[1]/a[2],地址
a+1偏移多少? a[0][0]☞a[1][0]
a[0]+1偏移多少?a[0][0]☞a[0][1]
2.a[0]、a[1]、a[2]既是一维数组名,而C语言规定了数组名就是首地址,因此a[0]代表一维数组a[0]中第0列元素的地址,即&a[0][0],也就是a[1]的值是&a[1][0],a[2]的值是&a[2][0]。
3.a[0]和 (a+0) 等价,a[1]和(a+1)等价,a[i]和*(a+i)等价,因此,a[0]+1和 *(a+0)+1 都是&a[0][1]的地址。
4.打印数组的两种方式
int main(){
int arr[3][4]={{1,3,5,7};{9,11,13,15};{17,19,21,23}};
int i;
int j;
for(i=0;i<3;i++){
for(j=0;j<4;j++){
printf(“add:0x%p,data:%d \n”,&arr[i][j],arr[i][j]);
printf(“add:0x%p,data:%d \n”,arr[i]+j,(arr[i]+j));
printf(“add:0x%p,data:%d \n”,(arr+i)+j,((arr+i)+j));
}
}
}
5 二维数组a的有关指针
二维数组名,指向一维数组a[0],即0行首地址 a
0行0列元素地址 a[0] *(a+0) *a
1行首地址 &a[1] a+1 //相对于在父数组,a是数组名a={{1,3,5,7};{9,11,13,15}}
1行0列元素a[1][0]的地址 a[1] *(a+1) //相对于在子数组,a[1]是数组名 a[1]={9,11,13,15}
1行2列元素a[1][2]的地址 a[1]+2 *(a+1)+2 &a[1][2]
1行2列元素a[1][2]的值 ( a[1]+2) * ((a+1)+2) a[1][2]
6.数组指针的定义
int main(){
int arr[3][4]={{1,3,5,7};{9,11,13,15};{17,19,21,23}};
int i;
int j;
//能不能定义一个指针,让指针偏移的时候,也偏移对应大小的数组?
//数组指针,定义一个指针,指向一个数组!
//数组指针才是真正等同于二维数组名
int (p2)[4];
p2=arr;
printf(“p2=%p\n”,p2)
printf(“++p2=%p\n”,++p2) //输出地址相比于P2偏移了16,即一行地址大小,如果不定义数组指针,直接定义一个p,p=arr,p++则偏移4个字节,和arr++偏移不符,出现警告报错
for(i=0;i<3;i++){
for(j=0;j<4;j++){
printf(“add:0x%p,data:%d \n”,(arr+i)+j,(*(arr+i)+j));
}
}
}
7 用函数封装的方式输出二维数组任意行列的值
#include <stdio.h>
void tipsInput(int *hang,int lie)
{
printf(“输入行和列:”);
scanf(“%d%d”,hang,lie);
}
void getData(int (p)[4],int hang,int lie)
{
printf(“值为:%d\n”,((p+hang)+lie));
}
int main(){
int arr[3][4]={{11,22,33,44},{55,66,77,88},{22,33,44,55}};
int ihang;
int ilie;
int data;
//提示用户输入行列
tipsInput(&ihang,&ilie);
//输出对应行列
getData(arr,ihang,ilie);
return 0;
}
8.函数指针
函数地址定义:如果在程序中定义了一个函数,在编译时,编译系统为函数代码分配一段存储空间,这段存储空间的起始地址(又称入口地址)称为这个函数的指针。
函数名就是地址!
如何定义一个函数指针变量(和普通变量一样)
int a; int *p;
char c ; char *p
int getData(int a, int b); int (*p)(int a, int b)
#include <stdio.h>
int inCData (int data)
{
return ++data;
}
void printWelcome ()
{
puts(“程序启动,欢迎使用\n”);
}
int main()
{
void (*p)();//定义一个函数指针变量
p=printWelcome;//指向函数
void (*p2)();
p2=inCData;
(*p)();//调用
printf("p2测试:%d\n",(*p2)(10););
return 0;
}
9.二级(多级)指针
存放指针变量的地址 int **p
当你通过函数调用来修改调用函数指针指向的时候
就像通过函数调用修改某变量的值的时候
10.各种指针的定义
1.一个整形数: int a;
2.一个指向整形数的指针: int *a;
3.一个指向指针的指针,它指向的指针指向一个整形数: int **a;
4.一个有10个整形数的数组:int a[10];
5.一个有10个指针的数组,每个指针指向一个整形数 int *a[10];
6.一个指向有10个整形数的数组的指针:int (*a)[10];
7.一个指向指针的指针,被指向的指针指向一个有10个整形数的数组:
int (**a)[10]
8.一个指向数组的指针,该数组有10个整形指针:int *(*a)[10];
9.一个指向函数的指针,该函数有一个整形参数并返回一个整形数:
int (*a)(int);
10:一个有10个指针的数组,每个指针指向一个函数,该函数有一个整形参数并返回一个整形数:int (a[10])(int);
11:一个函数的指针,指向的函数的类型是有两个整形参数并返回一个函数指针的函数,返回的函数指针指向有一个整形参数且返回整形数的函数:
int ((*a)(int,int))(int);