函数指针
1.在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。
2.把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数。
然后通过指针变量就可以找到并调用这个函数。
我们把这种指向函数的指针变量称为“函数指针变量”。
函数指针变量定义的一般形式为: 类型说明符 (*指针变量名)();
#include <stdio.h>
void print()
{
printf("hello\n");
}
int add(int x,int y)
{
int result=0;
result=x+y;
return result;
}
int main()
{
int a=3,b=2,ret;
void (*p)();//定义一个返回空类型的指针(*p)代表他是一个指针(*P)(void)代表他是一个函数。
p=print;//将函数的首地址给指针p,让p指向这个函数
p();调用print函数
int (*q)(int a,int b);//定义一个返回类型为整形的指针(int a ,int b)代表他是一个函数,形参为int a int b;
q=add;//将add首地址给指针q。让q指向add
ret=q(a,b);//用ret接受函数指针q,调用的函数add的返回值result
printf("%d\n",ret);
}
指针类型的函数
所谓函数类型是指函数返回值的类型。 在C语言中允许一个函数的返回值是一个指针(即地址),
这种返回指针值的函数称为指针型函数。
程序:
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
char* ptr()
{
char* str=(char*)malloc(sizeof(char)*100);
return str;//返回一个char*类型的指针
}
int main()
{
char*str;
str=ptr();//将ptr()//返回值给str,犹豫是个值,所以调用函数里面的指针str里面的值给了主函数里面的str;
strcpy(str,"hello");//由于调用函数里面的str值是mollac分配内存空间的地址,所以主函数str指向那段堆空间,使str指针可以使用不在是野指针。
printf("%s\n",str);
}
int(*p)() 和 int *p()区别
int (*p)()是一个变量说明,说明p是一个指向函数入口的指针变量,该函数的返回值是整型量,(*p)的两边的括号不能少。
int *p()则不是变量说明而是函数说明,说明p是一个指针型函数,其返回值是一个指向整型量的指针
指针与二维数组
指针数组:指针数组里面所有元素都是有相同存储类型并且指向相同数据类型的指针变量;
int *ap[3]; 表示ap是一个指针数组,它有三个数组元素,每个元素值都是一个指针,指向整型变量。
表示形式 | 含义 | 地址值 |
&a | 指向二维数组的指针,二维数组的地址 | 1000 |
a | 二维数组名,指向一维数组a[0],即第0行首地址 | 1000 |
a[0] , *(a+0) , *a | 第0行第0列元素地址 | 1000 |
a+1 , &a[1] | 第1行地址(加一行) | 1006 |
a[1] , *(a+1) | 第1行第0列元素地址 | 1006 |
a[1]+2 , *(a+1)+2 , &a[1][2] | 第1行第2列元素地址 | 1010 |
*(a[1]+2) , *(*(a+1)+2) , a[1][2] | 第1行第2列元素的值 | 元素值为11 |
二维数组+1分析图
数组指针:
指向数组的指针。例:int (*p)[10]; p即为指向有10个元素的一维数组的指针,又称数组指针。
二维数组指针:
int a [3][5];//列表达式必须一样
int (*str)[5]=a//这里说明a是一个二维数组名 ,str是一个指针变量,它指向包含5个int元素的一维数组.
str的增量以它所指向的 一维数组为长度 单位;
*(str+i)是一维数组a[i][0]的地址;
*(str+2)+3表示a[2][3]地址(第一行为0行,第一列为0列),*(*(str+2)+3)表示a[2][3]的值。
程序:
#include <stdio.h>
int main()
{
int a[3][4]={{1,2,3,4},{3,4,5,6},{5,6,7,8}};
int i;
int(*p)[4]=a;
int *q=a[0];
for(i=0;i<3;i++)
{
if(i==0)
{
(*p)[i+i/2]=*q+1;
}
else
{
p++;
++q;
}
}
for(i=0;i<3;i++)
{
printf("%d\n",a[i][i]);
}
printf("%d,%d\n",*((int*)p),*q);//强制转换成int*型,*()取值
}
输出:2,4,5,7,3
指针的指针
定义:一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。
格式:char **q;
程序:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void MemoryInit(char **str)//定义一个指针指向指针ptr所以指针的指针
{
*str = (char *)malloc(sizeof(char) * 64);//给str赋值,改变str所指向的ptr里面的值
}
int main()
{
char *ptr = NULL;//定义了一个空指针
MemoryInit(&ptr); //传ptr指针本身的地址
strcpy(ptr, "helloworld");
return 0
}
题目:
#include <stdio.h>
int main()
{
char *name[]={"ww","aa","jj","zz","hh"};
char **p;
int i;
for(i=0;i<5;i++)
{
p=name+i;//将name首地址赋给p,p指向0x100空间,0x100里面由于是指针数组,所以p指向一个指针,这个指针指向0x200.这样指针p里面就有了可以使用的值
printf("%s\n",*p);//取P所指向0x100空间里面的值,是一个指针也是地址访问所对应存有字符串的内存。
}
}
命令行参数:
main (int argc,char *argv[]) argc(第一个形参)必须是整型变量, argv( 第二个形参)必须是指向字符串的指针数组。argc名称可以随便改类型不能变;
int main(int argc, char *argv[])//argc用于计算输入常量的个数,*argv[]用于存放输入的常量
{
int i;
for (i = 1; i < argc; i++)
{
printf("%s\n", argv[i]);
}
return 0;
}
打印结果:
[root@localhost erwei]# ./argc ww dd wff ffsf
ww
dd
wff
ffsf
题目冒泡排序用函数指针修改:
#include <stdio.h>
int greater(int x, int y)
{
return (x > y) ? 1 : 0;
}
int less(int x, int y)
{
return (x < y) ? 1 : 0;
}
void GetArray(int a[], int length)
{
int i;
printf("Please input:\n");
for (i = 0; i < length; i++)
{
scanf("%d", &a[i]);
}
}
void sort(int a[], int length, int (*p)(int, int))//函数名作为实参传递用函数指针作为形参表示
{
int i, j, tmp;
for (i = 0; i < length - 1; i++)
{
for (j = 0; j < length - i - 1; j++)
{
//if (a[j + 1] < a[j])
if (p(a[j + 1], a[j]))//这里用指针调用函数输入实参
{
tmp = a[j + 1];
a[j + 1] = a[j];
a[j] = tmp;
}
}
}
}
void print(int a[], int length)
{
int i;
for (i = 0; i < length; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
int main()
{
int i, j, tmp;
int a[10] = {0};
int length = sizeof(a) / sizeof(a[0]);
GetArray(a, length);
sort(a, length, greater);//调用函数并传递greater函数入口地址,
print(a, length);
return 0;
}
题目:用命令行参数修改冒泡排序:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void GetArray(char *a[], int length)//对应char *argv
{
int i;
printf("Please input:\n");
for (i = 0; i < length; i++)
{
a[i] = (char *)malloc(sizeof(char) * 64);
scanf("%s", a[i]);
}
}
void sort(char *a[], int length)
{
int i, j;
char *tmp;
for (i = 1; i < length - 1; i++)
{
for (j = 1; j < length - i - 1; j++)
{
//if (a[j + 1] < a[j])
if (strcmp(a[j + 1], a[j]) > 0)
{
tmp = a[j + 1];
a[j + 1] = a[j];
a[j] = tmp;
}
}
}
}
void print(char *a[], int length)
{
int i;
for (i = 1; i < length; i++)
{
printf("%s ", a[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
int i, j, tmp;
//char *a[10] = {0};
int length = argc;//argc统计输入参数的个数
//GetArray(argv, length);//传递存储输入参数数组argc的首地址
sort(argv, length);
print(argv, length);
return 0;
}