指针与数组:数组指针、函数指针、函数指针数组

数组:

int arr[10]

arr:代表数组首元素的地址即&arr[0]

&arr:代表整个数组的地址。

int* p=arr;

int (*p1)=&arr;

数组名在两种情况下代表整个数组:

sizeof(arr) &arr+1

字符串指针

字符串在内存中仅有一份,在rodate段,不可修改

如果需要修改,拷贝一份到数组修改

int main()
{
    *str1="hello word";//"hello word"这个字符串在内存中仅有一份,在rodate段
    *str2="hello word";//不可修改,如果想要修改,放在数组中。
    *str3[]="hello word";
    *str4[]="hello word";
    //str1=str2   str3!=str4
    return 0;
}

指针数组与数组指针

指针数组:包含指针元素的数组   eg:void *p[10]

指针数组是一个只包含指针元素的数组,它的元素可以指向相同类型的不同对象

数组指针 : 指向一个数组的指针    eg: void (*p)[10]

    数组指针就是一个指针变量,它指向一个数组

数组指针的使用:存放数组的地址

int main()
{
    int arr[10]={0};
    printf("%d,%d\n",arr,&arr);//两个值一样,意义不一样
    //arr  数组首元素的地址&arr[0]   &arr整个数组的地址
    int *p=arr;
    int(*p2)[10]=&arr;//与数组指针类型匹配
}

数组指针的使用

一维数组

int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	int (*p2)[10] = &arr;
	printf("%d\n",  *( (*p2)+2) );//arr[2]   //*p2 ==  arr
	return 0;
}

二维数组:

void print_arr(int (*arr)[5], int row, int col) {
    int i = 0;
    for(i=0; i<row; i++)
   {
        for(j=0; j<col; j++)
       {
            printf("%d ", arr[i][j]);
                         //*(*(arr+i)+j)
       }
        printf("\n");
   }
}
int main()
{
    int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
    //数组名arr,表示首元素的地址
    //但是二维数组的首元素是二维数组的第一行  arr+1类型 int(*)[5]
    //可以数组指针来接收
    print_arr(arr, 3, 5);
    return 0; 
 }

数组传参:

一维数组

#include <stdio.h>
void test(int arr[])//ok
 {}
void test(int arr[10])//ok
 {}
void test(int *arr)//ok
 {}
void test2(int *arr[20])//ok
 {}
void test2(int **arr)//ok
 {}
// arr2 首元素的地址 元素类型int *
 //int *p; int**p1=&p;
int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0};
 test(arr);
 test2(arr2);
}

二维数组

void test(int arr[3][5])//ok
  {}
void test(int arr[][])//no
  {}
void test(int arr[][5])//ok
  {}
 //总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
void test(int *arr)//no  强转后可以传参
 {}
void test(int* arr[5])//no
 {}
void test(int (*arr)[5])//ok
 {}
void test(int **arr)//no    二级指针接受一级指针的地址。
 {}
int main()
{
  int arr[3][5] = {0};
  test(arr);
}

二维数组强转为一维数组传参

void Show(int *arr,int row,int col)
{
	int i = 0,j = 0;
	for(i = 0;i < row;i++)
	{
		for(j = 0;j < col;j++)
		{
			printf("%d ",arr[i*col+j]);
		}
		printf("\n");
	}
}
int main()
{
 int arr[3][5] = {0};
 Show((int *)arr,3,5);
}

指针传参

一级指针接收:相应类型变量的地址,数组名

二级指针接收:相应一级指针的地址,指针数组

指针函数:返回指针的函数

函数名代表函数的地址

函数指针:指向函数代码首地址的指针变量。

函数指针就是指向函数的存储空间地址的指针。可以对函数指针进行赋值并且通过函数指针来调用函数。

 

void (*p) ()

(* (void (*)() ) 0) ( );

调用0地址处不带参数且返回值为void的函数

解析:

    void(*)()函数指针类型

( void(*)() )0 将0强制转换为函数指针类型,0是一个地址,也就是说一个函数保存在首地址为0的一段区域内

*(void(*)() )0 取0地址开始的一段内存里面的内容,其内容就是保存在首地址为0的一段区域内的函数

(*(void(*)() )0)() 函数的调用。

void (* signal(int , void(*) (int) ) ) (int);

signal是一个函数,有两个参数,一个是int,一个是函数指针。

返回值是函数指针 void(*)(int)

void (* signal(int , void(*) (int) ) ) (int);代码简化 //也可以为 typedef void(*pFun)(int)

typedef void(*)(int) pFun;

pFun signal (int ,pFun);

void Function()
{
    printf("Call Function!\n");
}
int main()
{
    void(*p)();
    *(int*)&p=(int)Function;
     //&p  求p本身的地址,
    //(int*)&p将地址强制转换为指向int类型数据的指针
    //(int)Function 将函数的入口地址赋值给指针变量p
    (*p)();//对函数指针的调用。
    return 0;
}

使用函数指针的好处在于,可以将实现同一功能的多个模块统一起来标识,这样一来更容易后期的维护,系统结构更加清晰。或归纳为便于分层设计、利于系统抽象、降低耦合度以及接口与实现分开。

函数指针数组:

char *(*pf[3])(char * p)

它是一个数组,数组名为pf,数组内存储了3个指向函数的指针。这些指针指向一些返回值类型为指向字符的指针,参数为一个指向字符的指针的函数。

用途:转移表

指向函数数组的指针:

char* (*(*pf)[3]) (char * p)

pf是一个指针,指向了一个包含了3个元素的数组;这个数组里面存的是指向函数的指针;这些指针指向一些返回值类型为指向字符的指针,参数为一个指向字符的指针的函数。

函数指针数组和指向函数数组的指针

使用实例

#include<stdio.h>
#include<string.h>
char * fun1(char *p)
{
	printf("%s\n", p);
	return p;
}
char * fun2(char *p)
{
	printf("%s\n", p);
	return p;
}
char * fun3(char *p)
{
	printf("%s\n", p);
	return p;
}
int main()
{  
    char *(*a[3])(char *p);
	char *(*(*pf)[3])(char *p);
     pf=&a;
	a[0] = fun1;//可以直接用函数名
	a[1] = &fun2;//可以用函数名加上取地址符
	a[2] = fun3;

    a[0]("fun1"); 
	a[1]("fun2");
	a[2]("fun3");
	pf[0][0]("fun1");
	pf[1][1]("fun2");
	pf[2][2]("fun3");
	return 0;
}

发布了52 篇原创文章 · 获赞 6 · 访问量 1339

猜你喜欢

转载自blog.csdn.net/weixin_43519514/article/details/105413931
今日推荐