指向函数的指针变量
C语言:指针变量
C语言:指针变量声明指针变量:基数据类型 * 指针变量名如 int *p ;例:int *p1, *p2;p1和p2是int型指针变量,可以指向int型变量或int数组元素。
char *p3 ; p3是char型指针变量,可以指向char型变量或char数组元素。
指针变量可用来表示它所指向的变量(或数组元素)。
所指向变量的数据类型必须和指针变量的基数据类型相同。
(注:还可声明指向数组、结构、和函数等的指针变量。
)为了让指针变量指向某一变量,须把该变量的地址赋给这个指针变量:指针变量 = &所指向变量如 int k,*p ; p=&k;也可以把一个指针变量如p1的值赋给另一指针变量如p2:p2=p1,只要它们有相同的基数据类型。
此时,p2和p1指向同一变量:指针变量 1 = 指针变量 2 如 int k, *p1,*p2; p1=&k; p2=p1;例:int k, n, a[10], *p1, *p2 ; char c, s[20], *p3, *p4, *p5 ;p1 = &k ; p2 = &a[6] ; p3 = &c ; p4 = &s[0] ; p5 = p4;为引用指针变量所指向的变量,只须在该指针变量前加一星号:*指针变量,如 *p 。
例如, int k,*p; p=&k;接上例:*p1 = 100; /* 同 k=100; */n = *p1 + 5 ; /* 同 n=k+5; */*p4 = ’A’ ; /* 同 s[0]=’A’; */s[1]=*p4; /* 同 s[1]=s[0]; */对指向数组元素的指针变量,可以做整数加减法: 指针变量±整数如p2=p1+1;例如,设p1指向a[i]:p1=&a[i]; 则p1+m指向a[i+m], 即 *(p1+m) 是 a[i+m]。
例: int *p1,*p2, a[10]={0,1,2,3,4,5,6,7,8,9};p1=&a[0]; /* 也可写成p1=&a; 或p1=a; */p2=p1+8; /* p2指向a[8], 同 p2=&a[8] */printf(“%d,%d,%d”, *p1, *p2, *(p1+8) );/* 输出 0,8,8 */注意,数组名本身就代表数组首元素的地址,即:设a[]是数组,则a , &a , 和 &a[0]是一回事,都表示数组首元素的地址。
函数指针和指针函数用法和区别
函数指针和指针函数用法和区别函数指针和指针函数(pointerfunction)是C语言编程中常用的技术,在一些高级编程技术(例如设计模式)中也有广泛的应用。
它们的概念比较复杂,有时候会让初学者有点晕头,但是一旦理解了它们的用法和区别,大家就会发现它们对于结构化编程的设计有着重要的意义。
本文尝试以最简单的方式阐述函数指针和指针函数的用法和区别。
首先,在我们讨论函数指针和指针函数之前,我们最好以一个函数为例来介绍它们:void foo (int a, int b){int c = a + b;printf(%dc);}foo函数接收两个整数参数a和b,并将它们相加后输出结果。
接下来我们来看看函数指针是什么:函数指针(function pointer)是一种指向函数的指针,它可以把函数的地址保存在指针变量中,这样你就可以通过指针调用函数。
句话说,它实际上指向一个函数,通过调用它,你可以调用函数。
函数指针的声明可以形式如下:void (*fooPtr)(int, int);其中,fooPtr是函数指针变量,函数指针变量fooPtr可以指向函数foo()。
函数指针可以赋值,例如:fooPtr=foo;此外,你可以使用函数指针调用函数,例如:(*fooPtr)(1,2);这里,可以说fooPtr指向函数foo(),并且调用函数foo()。
现在,让我们来看看指针函数是什么:指针函数(pointer function)是一种特殊的函数,其返回值类型是指针,即它是一种不接受参数并返回指针的函数。
指针函数的声明可以形式如下:int *fooPtr(void);其中,fooPtr()是指针函数,它返回一个int类型的指针。
指针函数可以调用,例如:int *p = fooPtr();这里,fooPtr()调用了指针函数,并将返回的指针赋值给*p。
了解了函数指针和指针函数的基本概念及其用法后,那么函数指针和指针函数有什么区别?函数指针和指针函数的主要区别在于,函数指针可以指向任何函数,而指针函数必须返回指针类型的变量,并且不接受任何参数。
《C语言程序设计》第8章指针
10.3.3 指针变量和数组作函数参数 数组名作形参时,接收实参数组的起始地址;
作实参时,将数组的起始地址传递给形参数组。
引入指向数组的指针变量后,数组及指向数 组的指针变量作函数参数时,可有4种等价形式 (本质上是一种,即指针数据作函数参数):
(1)形参、实参都用数组名 (2)形参、实参都用指针变量 (3)形参用指针变量、实参用数组名 (4)形参用数组名、实参用指针变量
(4)指针变量的++、--与&、*的结合
对于指针变量的++、--与&、*的结合 使用,关键要注意按照运算符的优先级和 结合性进行。
例如: int a=2, *p; p=&a;
•表达式:(*p)++,按运算符的优先级,等价于 a++。其含义为:取出指针变量p所指向的内存单 元的值(即a的值),a的值加1,送回a的内存单 元,a的值变为3,p的值未发生变化,仍然指向 变量a。
程序说明:printf("%s\n",s);语句 通过指向字符串的指针变量s,整体引
用它所指向的字符串的原理:系统首先输出s 指向的第一个字符,然后使s自动加1,使 之指向下一个字符;重复上述过程,直至遇到 字符串结束标志。
main() { char string[ ]=”I love Beijing.”; printf(“%s\n”,string); }
3.数组元素的引用 数组元素的引用,既可用下标法,也可用
指针法。
10.3.2 通过指针引用数组元素 如果有“int a [10],*p=a;” ,则: (1)p+i和a+i都是数组元素a [i]的地址。
(2)*(p+i)和*(a+i)就是数组元素a [i]。 int a [3]; a [0]——*a a [1]——*(a +1) a [2]——*(a +2)
C语言中指针变量作为函数参数详解
C语言中指针变量作为函数参数详解C语言中指针变量作为函数参数详解在C语言中,函数的参数不仅可以是整数、小数、字符等具体的数据,还可以是指向它们的指针。
用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。
像数组、字符串、动态分配的内存等都是一系列数据的集合,没有办法通过一个参数全部传入函数内部,只能传递它们的指针,在函数内部通过指针来影响这些数据集合。
有的时候,对于整数、小数、字符等基本类型数据的操作也必须要借助指针,一个典型的例子就是交换两个变量的值。
有些初学者可能会使用下面的方法来交换两个变量的值:#includevoid swap(int a, int b){ int temp; //临时变量 temp = a; a = b; b = temp;}int main(){ int a = 66, b = 99; swap(a, b); printf("a = %d, b = %dn", a, b); return 0;}运行结果:a = 66,b = 99从结果可以看出,a、b 的值并没有发生改变,交换失败。
这是因为 swap() 函数内部的 a、b 和 main() 函数内部的 a、b 是不同的变量,占用不同的内存,它们除了名字一样,没有其他任何关系,swap() 交换的是它内部 a、b 的值,不会影响它外部(main() 内部)a、b 的值。
改用指针变量作参数后就很容易解决上面的问题:#includevoid swap(int *p1, int *p2){ int temp; //临时变量temp = *p1; *p1 = *p2; *p2 = temp;}int main(){ int a = 66, b = 99; swap(&a, &b); printf("a = %d, b = %dn", a, b); return 0;} 运行结果:a = 99,b = 66调用 swap() 函数时,将变量 a、b 的地址分别赋值给 p1、p2,这样 *p1、*p2 代表的就是变量 a、b 本身,交换 *p1、*p2 的值也就是交换 a、b 的值。
定义函数指针
函数指针
将函数的首个地址(入口地址)赋予一个指针变量,使指针变量指向函数所在的内存空间,然后通过指针变量就可以找到并调用函数。
这种指针就是函数指针。
函数指针的定义格式为:
数据类型符(*指针名)(参数表);
int (*p)(int n);
因为()的优先级高于“*”,所以指针名的括号不能省略。
如果省略,则为返回值为指针的函数原型。
说明:
●数据类型符是指指针返回值的类型。
●定义指向函数的指针变量,并不意味着这个指针变量可以指向任何函数,它只能指向在
定义时指定的类型的函数。
●如果要用指针调用函数,必须先使指针变量指向该函数
●在给函数指针变量赋值使,只需给出函数名而不必给出参数
●要用函数指针变量调用函数时,只需将(*p)代替函数名即可,在(*p)之后的括号中根据
需要写上实参
●对指向函数的指针变量不能进行算术运算
●用函数名调用函数,只能调用所指定的一个函数,而通过指针变量调用函数比较灵活,
可以根据不同情况先后调用不同的函数。
●指向函数的指针变量的一个重要的用途是把函数的地址作为参数传递给其他函数,这样
就能够在被调的函数中使用实参函数。
c语言二级指针详解
c语言二级指针详解C语言中,指针是一种重要的数据类型,它可以指向另一个变量或者数据结构中的一个元素,并且可以进行不同种类的操作(如解引用、赋值、比较、运算等)。
在C语言中,指针本身也是一个变量,它具有一个内存地址,并且其值就是指向的地址。
而指针变量可以通过指定自己的类型来控制指向的变量或者数据结构元素的类型。
在C语言中,指针本身也可以被指针所指向,这样的指针就被称为“二级指针”或者“指向指针的指针”。
二级指针在一些情况下比普通指针更加灵活,比如当我们需要在函数内部进行指针变量的修改或者返回值时,就可以使用二级指针。
1、指向指针的指针需要使用两个星号(**)来声明,例如:int **p;2、在函数中传递指向指针的指针时,需要将变量的地址传递给函数,而函数需要使用指向指针的指针来访问实际的指针变量。
3、在使用二级指针时,我们需要防止指针变量指向非法内存地址,否则会导致程序出现意想不到的错误。
二级指针是C语言中非常重要的概念,尤其在函数调用和指针变量的修改或返回值时,更是非常有用。
不过,我们在使用二级指针时需要额外注意指向内存地址的合法性,否则会导致程序出现异常。
二级指针是指指向指针对象的指针,即指针的指针,它可以通过间接的方式访问一个指针变量所指向的地址,这种间接的访问方式可以增加程序的灵活性,从而使程序更加易于理解和维护。
1、动态内存管理在C语言中,动态内存分配是通过调用malloc函数来实现的,而释放动态内存则需要使用free函数。
在使用malloc函数分配内存时,它会返回一个指针,指向分配的内存空间的首地址,我们可以将这个指针赋值给一个普通的指针变量,然后通过这个普通指针变量来访问分配的内存空间。
不过,当我们使用malloc来分配一个指针数组时,我们就需要使用二级指针来存储这个指针数组的首地址。
int **p = (int **)malloc(sizeof(int *) * 10);for (int i = 0; i < 10; ++i) {p[i] = (int *)malloc(sizeof(int) * 10);}以上代码中,我们使用了二级指针来存储指向指针数组的地址,然后使用循环语句来为每一个指针分配空间。
c语言中 指针的类型
c语言中指针的类型在C语言中,指针是一种非常重要的概念。
它是一个变量,其值为内存地址。
通过使用指针,我们可以直接访问和修改内存中的数据,这使得我们能够更高效地处理数据和实现复杂的数据结构。
在C语言中,指针的类型决定了指针变量可以指向的数据类型。
以下是一些常见的指针类型:1. void指针:void指针是一个通用的指针类型,可以指向任意类型的数据。
它的定义方式为void *ptr。
由于void指针没有具体的数据类型信息,因此在使用时需要进行强制类型转换。
2.整型指针:整型指针可以指向整型数据。
例如,int *ptr可以指向一个int类型的变量。
可以使用指针来操作该变量的地址,读取或修改其值。
3.浮点型指针:浮点型指针可以指向浮点型数据。
例如,float*ptr可以指向一个float类型的变量。
使用指针可以更高效地进行浮点计算,同时可以实现对浮点数据的修改。
4.字符型指针:字符型指针可以指向字符型数据。
例如,char*ptr可以指向一个字符型变量或字符数组。
通过指针,我们可以更方便地操作字符串,包括拷贝、连接、查找等。
5.结构体指针:结构体指针可以指向结构体类型的数据。
结构体是一种自定义的数据类型,可以包含多个不同数据类型的成员变量。
通过结构体指针,我们可以访问和修改结构体的成员,实现对结构体的操作。
6.数组指针:数组指针可以指向数组类型的数据。
例如,int*ptr可以指向一个int类型的数组。
通过指针,我们可以遍历数组中的每个元素,进行读取、修改或其他操作。
7.函数指针:函数指针可以指向函数。
函数是一段可执行的代码块,通过函数指针,我们可以像调用普通函数一样调用被指向的函数。
8.指向指针的指针:指向指针的指针是指针的指针,通过它可以实现更复杂的数据结构,如链表、二维数组等。
在C语言中,指针的类型非常灵活,可以根据实际需求选择合适的指针类型。
通过使用指针,我们可以提高程序的效率和灵活性,同时能够更方便地进行内存管理和数据操作。
指针
(main)
9 5 5 9 2000 2002
(swap)
2000 2002 5
...
…...
整型变量a 整型变量b 指针pointer_1 指针pointer_2
指针p1 指针p2
整型p
例 将数从大到小输出
swap(int *p1, int *p2) { int p; 2000 p=*p1; 2002 *p1=*p2; 2004 *p2=p; 2006 } 地址传递 2008 main() 200A { int a,b; int *pointer_1,*pointer_2; 200C scanf("%d,%d",&a,&b); 200E pointer_1=&a; pointer_2=&b; 2010 if(a<b)swap(pointer_1,pointer_2); printf("\n%d,%d\n",a,b); }
#define NULL 0 int *p=NULL:
p=NULL与未对p赋值不同 用途: 避免指针变量的非法引用 在程序中常作为状态比较
例 例 char *p; int *p1; ...... void *p2; while(p!=NULL) p1=(char *)p2; { ...… p2=(void *)p1; } 表示不指定p是指向哪一种 类型数据的指针变量
…...
例
整型变量i
i=3;-----直接访问
2000 2001 2002 2003 2004 3 20 10
变量i_pointer 2000
2005
2006
指针变量
例
*i_pointer=20; -----间接访问
函数指针的调用
函数指针的调用
函数指针是指向函数的指针变量,它可以用来调用函数。
使用函数指针可以动态地选择要调用的函数,从而增强程序的灵活性和扩展性。
函数指针的调用步骤如下:
1. 定义函数指针变量:要调用的函数的参数类型和返回值类型必须与函数指针变量的类型一致。
2. 将函数的地址赋给函数指针变量:可以使用函数名或者地址运算符&来获取函数的地址。
3. 通过函数指针调用函数:使用函数指针变量加上括号和参数列表来调用函数。
例如,假设有以下函数和函数指针变量:
```
int max(int a, int b) {
return a > b ? a : b;
}
int (*p)(int, int); // 定义函数指针变量p
```
可以通过以下步骤来调用函数:
```
p = max; // 将函数max的地址赋给函数指针p
int result = (*p)(3, 5); // 通过函数指针调用函数max,传
入参数3和5,得到返回值8
```
通过函数指针,可以实现函数的动态调用,提高程序的灵活性和可扩展性。
c语言中结构体 函数指针 内存对齐
c语言中结构体函数指针内存对齐C语言中的结构体、函数指针和内存对齐是编程中常见且重要的概念。
结构体是一种自定义的数据类型,可以将不同类型的数据组合在一起,形成一个新的数据类型。
函数指针是指向函数的指针变量,可以用来传递函数作为参数或者在运行时动态调用函数。
内存对齐是指在分配内存时,按照一定规则将数据存储在内存中,以提高访问效率。
我们来了解一下结构体。
结构体是由多个不同类型的数据组成的数据类型,可以将这些数据看作一个整体来处理。
在C语言中,我们可以使用关键字struct来定义一个结构体。
例如,我们可以定义一个表示学生信息的结构体:```struct Student {int id;char name[20];int age;};```在这个结构体中,我们定义了三个成员变量:id、name和age。
id 是一个整型变量,name是一个字符数组,age是一个整型变量。
结构体的成员变量可以是任意的数据类型,包括基本数据类型、数组、指针等。
接下来,我们来介绍一下函数指针。
函数指针是指向函数的指针变量,可以用来传递函数作为参数或者在运行时动态调用函数。
在C 语言中,我们可以通过定义函数指针变量的方式来声明一个函数指针。
例如,我们可以定义一个函数指针变量,指向一个返回值为整型、参数为两个整型的函数:```int (*p)(int, int);```在这个例子中,我们定义了一个名为p的函数指针变量,它指向一个返回值为整型、参数为两个整型的函数。
通过函数指针,我们可以实现回调函数的功能,即将一个函数作为参数传递给另一个函数,并在需要的时候调用它。
我们来了解一下内存对齐。
内存对齐是指在分配内存时,按照一定规则将数据存储在内存中,以提高访问效率。
在C语言中,编译器会根据平台的要求对数据进行对齐。
对齐的规则通常是将数据存储在地址能够被其类型的大小整除的位置上。
例如,对于一个int类型的变量,它的大小为4个字节,在32位系统中,它的地址必须是4的倍数,即地址的低两位必须为0。
函数指针与指针函数
指针变量可以指向变量地址、数组、字符串、 指针变量可以指向变量地址、数组、字符串、动 态分配地址,同时也可指向函数, 态分配地址,同时也可指向函数,每一个函数在编译 系统会分配给该函数一个人口地址, 时,系统会分配给该函数一个人口地址,函数名表示 这个人口地址,那么, 这个人口地址,那么,指向函数的指针变量称之函数 指针变量. 指针变量
[例7.23]下列程序的可执行文件名为test.exe。 23]下列程序的可执行文件名为test exe。 test. argc, main(int argc,char *argv[]) { int i; printf(“argc= argc); printf(“argc=%d\n”,argc); for(i= i<argc; for(i=1;i<argc;i++) printf(” argv[i]); printf(”%s\n”,argv[i]); } 在操作系统提示符下,输入如下命令行: 在操作系统提示符下,输入如下命令行:
│2x - 1.76 │ fun1(x)=───────── (x-0.3)(10.5 -x) (x-
Cos(x-1.3) Cos(x-
例如:fun1( 例如:fun1( 1.66 ) = -0.806 ****************************************************** *******************/
*********************************************************/
fun( char str1[], char str2[]) { /*================================================*/ int i,j,k,len,len1; char ch; i<len len=strlen(str1); strcpy(str2,""); k=0; for (i=0;i<len-1;i++) { ch=str1[i]; ; if (ch>='A' && ch<='Z') ch=ch+32 else if ( ch>='a' && ch<='z' ) ch=ch-32; str2[k]=ch; k++; } str2[k]='\0'; /*-------------------------------------------------------*/ }
C语言程序设计教程(第5版)王秀鸾第10章函数参数传递进阶
10.6 main( )函数的形参
主函数的原形如下: main(int argc,char *argv[]) { … }
其中,argc和argv就是main()函数的形参。argc 是整形变量,argv[]是一个字符型指针数组。
main( )函数是由操作系统调用的,它的参数由操 作系统传递,所以运行带形参的主函数时,必须在 操作系统命令状态下,输入命令行:
第10章 函数参数传递进阶
10.1 指针变量作为函数参数
• 函数的参数不仅可以是整型、实型、字符型等数据,还可以是指
针类型数据。
【例10.1】交换两个指针变量所指向的变量的值
#include "stdio.h" void test(int *p1,int *p2) /* 形参为指针变量 */ { int p;
} int add(int a,int b) { return(a+b); }
3.指向函数指针变量作函数参数
指向函数的指针变量也可以作为函数的参数;即 将函数的入口地址传递给函数,也就是将函数名传 给形参,从而实现利用相同的函数调用语句调用不 同函数的目的。
【例】 用函数指针变量实现四则运算。
#include "stdio.h" double add(double x,double y) { return(x+y);} double sub(double x,double y) { return(x-y);} double mult(double x,double y) { return(x*y);} double divi(double x,double y) { return(x/y);} double result(double x,double y,doubl
c语言 指针
printf("The float value %f\n",*p2); } main( ) { int a=5,*p_int; float b=4.5,*p_float; p_int=&a; p_float=&b; outval(p_int,p_float); }
is
● 把一个指针变量的值赋予指向 相同类型变量的另一个指针变量。例如: int a,*pa=&a,*pb; pb=pa; /*把a的地址赋予指 针变量pb*/ 由于pa,pb均为指向整型变量的指 针变量,因此可以相互赋值。
● 把数组的首地址赋予指向数组 的指针变量。例如: int a[5],*pa; pa=a; /*数组名表示数组的首地 址,故可赋予指向数组的指针变量pa*/也 可写为 pa=&a[0]; /*数组第一个元素的 地址也是整个数组的首地址,也可赋予 pa*/ 当然也可采取初始化赋值的方法: int a[5],*pa=a;
指针变量加或减一个整数n的意 义是把指针指向的当前位置(指向某个数 组元素)向前或向后移动n个位置。 应当注意,数组指针变量向前或 向后移动一个位置和地址值加1或减1在 概念上是完全不同的。如果指针变量加1, 表示指针变量移动1个位置指向下一个数 据元素的首地址。而不是在原地址值的 基础上真实地加数值1。例如:
(5) 在函数outval调用结束后,形 参变量p1和p2将被释放,实参变量p_int 和p_float保留原指向。 (6) 如果在函数outval中,利用指 针对变量a和b的值做了改变,则函数调 用结束后,该变化将会影响至主函数。
【例9.3】 /*程序功能:指针变量作为函数 的参数参与传递,并对主函数的变量值 产生影响*/ outval(int *p1,float *p2) { *p1=*p1*10; *p2=*p2*10.; } main( ) { int a=5,*p_int; float b=4.5,*p_float;
C语言_指针变量的赋值与运算,很详细
C语⾔_指针变量的赋值与运算,很详细指针变量的赋值指针变量同普通变量⼀样,使⽤之前不仅要定义说明,⽽且必须赋予具体的值。
未经赋值的指针变量不能使⽤,否则将造成系统混乱,甚⾄死机。
指针变量的赋值只能赋予地址,决不能赋予任何其它数据,否则将引起错误。
在C语⾔中,变量的地址是由编译系统分配的,对⽤户完全透明,⽤户不知道变量的具体地址。
C语⾔中提供了地址运算符&来表⽰变量的地址。
其⼀般形式为: & 变量名;如&a变⽰变量a 的地址,&b表⽰变量b的地址。
变量本⾝必须预先说明。
设有指向整型变量的指针变量p,如要把整型变量a 的地址赋予p可以有以下两种⽅式:(1)指针变量初始化的⽅法 int a;int *p=&a;(2)赋值语句的⽅法 int a;int *p;p=&a;不允许把⼀个数赋予指针变量,故下⾯的赋值是错误的: int *p;p=1000; 被赋值的指针变量前不能再加“*”说明符,如写为*p=&a 也是错误的。
指针变量的运算指针变量可以进⾏某些运算,但其运算的种类是有限的。
它只能进⾏赋值运算和部分算术运算及关系运算。
指针运算符1.取地址运算符& 取地址运算符&是单⽬运算符,其结合性为⾃右⾄左,其功能是取变量的地址。
2.取内容运算符* 取内容运算符*是单⽬运算符,其结合性为⾃右⾄左,⽤来表⽰指针变量所指的变量。
在*运算符之后跟的变量必须是指针变量。
需要注意的是指针运算符*和指针变量说明中的指针说明符* 不是⼀回事。
在指针变量说明中,“*”是类型说明符,表⽰其后的变量是指针类型。
⽽表达式中出现的“*”则是⼀个运算符⽤以表⽰指针变量所指的变量。
main(){int a=5,*p=&a;printf ("%d",*p);}......//表⽰指针变量p取得了整型变量a的地址。
本语句表⽰输出变量a的值。
赋值运算指针变量的赋值运算有以下⼏种形式:1:指针变量初始化赋值。
C语言指针讲解
float a;
int * pointer_1;
pointer_1=&a;
编辑课件
9
在对指针变量赋值时需要注意两点:
⑴ 指针变量中只能存放地址(指针),不要将一个 整数赋给一个指针变量。
例: * pointer_1=100; /* pointer_1是指针 变量,100是整数,不合法 */
(2) 赋给指针变量的变是量地址不能是任意的类型, 而只能是与指针变量的基类型具有相同类型的变 量的
编辑课件
22
可以用一个指针变量指向一个数组元素。
例如:int a[10]; (定义a为包含10个整型数据的数组)
int *p; (定义p为指向整型变量的指针变量)
p=&a[0]; (把a[0]元素的地址赋给指针变量p) 也就是使p指向a数组的第0号元素 。
编辑课件
23
编辑课件
24
10.3.2 指针的运算
编辑课件
29
(3) 用指针变量指向数组元素。
#include <stdio.h> void main() { int a[10];
int *p,i; for(i=0;i<10;i++)
scanf(″%d″,&a[i]); printf(″\n″); for(p=a;p<(a+10);p++)
printf(″%d ″,*p); }
{ void exchange(int *q1, int *q2, int *q3);
int a,b,c,*p1,*p2,*p3;
scanf(″%d,%d,%d″,&a, &b, &c);
p1=&a;p2=&b;p3=&c;
exchange (p1,p2,p3);
深入解析C语言中函数指针的定义与使用
深⼊解析C语⾔中函数指针的定义与使⽤1.函数指针的定义函数是由执⾏语句组成的指令序列或者代码,这些代码的有序集合根据其⼤⼩被分配到⼀定的内存空间中,这⼀⽚内存空间的起始地址就成为函数的地址,不同的函数有不同的函数地址,编译器通过函数名来索引函数的⼊⼝地址,为了⽅便操作类型属性相同的函数,c/c++引⼊了函数指针,函数指针就是指向代码⼊⼝地址的指针,是指向函数的指针变量。
因⽽“函数指针”本⾝⾸先应该是指针变量,只不过该指针变量指向函数。
这正如⽤指针变量可指向整形变量、字符型、数组⼀样,这⾥是指向函数。
C在编译时,每⼀个函数都有⼀个⼊⼝地址,该⼊⼝地址就是函数指针所指向的地址。
有了指向函数的指针变量后,可⽤该指针变量调⽤函数,就如同⽤指针变量可引⽤其他类型变量⼀样,在这些概念上是⼀致的。
函数指针有两个⽤途:调⽤函数和做函数的参数。
函数指针的声明⽅法为:数据类型标志符 (指针变量名) (形参列表);“函数类型”说明函数的返回类型,由于“()”的优先级⾼于“*”,所以指针变量名外的括号必不可少,后⾯的“形参列表”表⽰指针变量指向的函数所带的参数列表。
例如: int function(int x,int y); /* 声明⼀个函数 */ int (*f) (int x,int y); /* 声明⼀个函数指针 */ f=function; /* 将function函数的⾸地址赋给指针f */ 赋值时函数function不带括号,也不带参数,由于function代表函数的⾸地址,因此经过赋值以后,指针f就指向函数function(int x,int y);的代码的⾸地址。
2.函数指针使⽤的例⼦ 知道了如何定义⼀个函数指针,但如何来使⽤它呢?先看如下例⼦:#include <stdio.h>#include <string.h>char * fun(char * p1,char * p2){ int i = 0; i = strcmp(p1,p2); if (0 == i) { return p1; } else { return p2; }}int main(){ char * (*pf)(char * p1,char * p2); pf = &fun; (*pf) ("aa","bb"); return 0;} 我们使⽤指针的时候,需要通过钥匙(“*”)来取其指向的内存⾥⾯的值,函数指针使⽤也如此。
指针的三种表示方法
指针的三种表示方法
指针是C语言中一种重要的数据类型,它是用来存储变量地址的。
在C语言中,指针可以用三种方式来表示,分别是指针变量、指针常量和指向指针的指针。
1. 指针变量
指针变量是指存储变量地址的变量。
它的声明方式为:数据类型*变量名;其中,数据类型表示指针变量所指向的数据类型,而变量
名则是指针变量的名称。
指针变量可以通过取地址符&来获取变量的
地址,并且可以通过解引用符*来访问指针变量所指向的变量。
2. 指针常量
指针常量是指不能改变其所指向的变量地址的指针。
它的声明方式为:const 数据类型 *变量名;其中,const关键字表示该指针常量的值不可被修改。
指针常量可以用于函数参数中,以确保函数内部不会修改该指针所指向的变量地址。
3. 指向指针的指针
指向指针的指针是指一个指针变量指向另一个指针变量的地址。
它的声明方式为:数据类型 **变量名;其中,数据类型表示指向指
针变量所指向的数据类型,而变量名则是指向指针的指针的名称。
指向指针的指针可以用于多级指针的情况,如在动态内存分配中的链表或树等数据结构中。
以上就是指针的三种表示方法,掌握它们对于学习C语言编程非常重要。
C语言6-指针
int a; int *p1; 指针p1 变量a
&a 目标变量p1
P1=&a;
&运算和*运算
&运算和*运算都属于单目运算,&要求运算量是变量或数
组元素,(取地址运算符)其形式为: & 变量名或数组元素名 其含义为取指定变量或数组元素的地址 *运算符要求运算量是地址,(指针运算符——间址运 算符)其形式为: *指针变量名或目标变量地址 含义为访问指定地址的目标变量 如: int i , j; int *p_1 , *p_2; p_1=&i; p_2=&j;
可见,指针p±n的运算并非内存地址含义上的运 算,而是C语言含义的地址运算。这种运算,一般 应在相同数据类型的存储区域上操作才有实际意 义,因此指针和数组关系密切,后图表示了这种 情况。
int a[40],*pa; pa-4 pa-3 pa-2 pa-1 pa pa+1 pa+2 pa+3 pa+4 a[ i –4] a[ i –3] a[ i –2] a[ i -1] a[ i ] a[i+1] a[i+2] a[i+3] a[i+4] (pa-4) (pa-3) (pa-2) (pa-1) pa (pa+1) (pa+2) (pa+3) (pa+4) 2004 2006 2008 2010 2012 2014 2016 2018 2020
运行情况如下: a=5,b=9 max=9,min=5
注: 程序中,a和b的值并未改变,但a1、a2的值已经改变, 因为程序始终让a1指向较小者,a2指向较大者,算法采取不 交换整型变量的值而交换指针变量的值的方法。 使用指针处理数据时,指针在使用前必须被赋予一定的地址 值或指定为空指针。一个没有赋值的指针其指向是不定的。 使用指针未定的指针接收数据时,常常会破坏内存中其它领 域的内容,甚至造成系统失控,应注意避免。例如下面对指 针p的使用是不恰当的:
指向函数的指针
指向函数的指针指向函数的指针变量的⼀般形式为:数据类型(*指针变量名)(函数参数表列);如: int (*p)(int ,int );1、int (*p)(int ,int );表⽰定义⼀个指向函数的指针变量p,它不是固定只能指向某⼀个函数。
在⼀个程序中,⼀个指针变量可以先后指向同类型的不同函数。
2、给函数指针赋值时,只须给出函数名⽽不必给出参数。
如: p=max;如果写成 p=max(a,b); 是将函数max(a,b);所得到的函数值赋给p,⽽不是将函数⼊⼝赋给p。
3、⽤函数指针变量调⽤函数时,只须将(*p)代替函数名即可。
如: c=(*p)(a,b);4、指向函数的指针变量,像p+n、p++、p--等运算是⽆意义的。
代码:输⼊两个整数,然后⽤户选择1或2,选1输出较⼤值,选2输出较⼩值。
程序代码:#include<stdio.h>void main(){int max(int ,int );int min(int ,int );int (*p)(int ,int );int a,b,c,n;printf("please enter a and b:");scanf("%d%d",&a,&b);printf("please choose 1 or 2:");scanf("%d",&n);if(n==1)p=max;else if(n==2)p=min;c=(*p)(a,b);printf("a=%d,b=%d,",a,b);if(n==1)printf("max=%d\n",c);elseprintf("min=%d\n",c);}int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a<b?a:b;}运⾏结果:实⽤价值在于在应⽤程序中常⽤菜单提⽰输出⼀个数字,然后根据不同值执⾏不同的功能,就是⽤此法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.一般定义形式:返回值的数据类型(*指针变量名)();for example: int function(int a, int b){...;}int (*pointer_of_function)();pointer_of_function = function; //相关联的语句就是这么简单。
2.函数的调用可以通过函数名调用,也可以通过函数指针调用(即用指向函数的指针变量调用)。
3.(*p)() 表示定义一个指向函数的指针变量,它不是固定指向哪一个函数的,而只是表示定义了这样一个类型的变量,它是专门用来存放函数的入口地址的。
在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。
在一个程序中,一个指针变量可以先后指向返回类型相同的不同的函数。
4.在给函数指针变量赋值时,只需给出函数名而不必给出参数,如:pointer_of_function = function ,因为是将函数入口地址赋给pointer_of_function, 而不牵涉到实参与形参结合的问题。
不能写成pointer_of_function = function(a,b)。
5.用函数指针变量调用函数时,只需将(*P)代替函数名即可,在(*p)之后的括弧中根据需要写上实参。
6.对指向函数的指针变量,像p++ 等类似运算是没有意义的。
7.区别int (*p)() 与int *p():由于()的优先级高于*,它就成了声明一个函数了,这个函数的返回值是指向整形变量的指针。
1 定义和调用程序在编译后,每个函数都有一个首地址(也就是函数第一条指令的地址),这个地址称为函数的指针。
可以定义指向函数的指针变量,使用指针变量间接调用函数。
下面通过一个简单的例子来说明:float max(float x,float y){return x>y?x:y;}float min(float x,float y){return x<y?x:y;}main(){float a=1,b=2, c;float (*p)(float x, float y);p=max;c=(*p)(a,b); /*等效于max(a,b)*/printf("\nmax=%f",c);p=min;c=(*p)(a,b); /*等效于min(a,b)*/printf("\nmin=%f",c);}程序运行的结果为:max=2.000000min=1.000000说明:(1)语句float (*p)(float x, float y);定义了一个指向函数的指针变量。
函数的格式是:返回值为float型,形式参数列表是(float x, float y)。
p定义后,可以指向任何满足该格式的函数。
(2)定义指向函数的指针变量的格式为:(3)数据类型(*指针变量名称)(形式参数列表);(4)其中数据类型是函数返回值的类型,形式参数列表是函数的形式参数列表。
(5)形式参数列表中,参数名称可以省略。
比如,float (*p)(float x, float y);可以写为:(6)float (*p)(float, float);(7)注意指针变量名称两边的括号不能省略。
(8)语句p=max;将max函数的首地址值赋给指针变量p,也就是使p指向函数max。
C语言中,函数名称代表函数的首地址。
(9)第一个c=(*p)(a,b);语句:由于p指向了max函数的首地址,(*p)(a,b)完全等效于max(a,b)。
函数返回2.0。
注意*p两边的括号不能省略。
(10)语句p=min; 将min函数的首地址值赋给指针变量p。
p是一个变量,p的值实际上是一个内存地址值,可以指向max,也可以指向min,但指向函数的格式必须与p的定义相符合。
(11)第二个c=(*p)(a,b);语句:由于p指向了min函数的首地址,(*p)(a,b)完全等效于min(a,b)。
函数返回1.0。
(12)将函数首地址赋给指针变量时,直接写函数名称即可,不用写括号和函数参数。
(13)利用指针变量调用函数时,要写明函数的实际参数。
提示:定义一个指向函数的指针变量时,一定要使用括号。
比较下面的两个定义:float (*p1)(int x, long y);float *p2(int x, long y);第一个语句定义了一个指向函数的指针变量p1;第二个语句声明了一个函数p2,p2的形式参数为(int x, long y),返回值为一个float型的指针。
2 指向函数的指针作为函数参数有时候,许多函数功能不同,但它们的返回值和形式参数列表都相同。
这种情况下,可以构造一个通用的函数,把函数的指针作为函数参数,这样有利于进行程序的模块化设计。
比如下面的例子中,我们把对2个float型数进行加、减、乘、除操作的4个函数归纳成一个数学操作函数MathFunc。
这样,在调用MathFunc函数时,只要将具体函数名称作为函数实际参数,MathFunc就会自动调用相应的加、减、乘、除函数,并计算出结果。
下面是程序的代码:float Plus(float f1, float f2);float Minus(float f1, float f2);float Multiply(float f1, float f2);float Divide(float f1, float f2);float MathFunc(float (*p)(float, float), float para1,float para2);main(){float a=1.5, b=2.5;printf("\na+b=%f", MathFunc(Plus, a,b));printf("\na-b=%f", MathFunc(Minus, a,b));printf("\na*b=%f", MathFunc(Multiply, a,b));printf("\na/b=%f", MathFunc(Divide, a,b));}float Plus(float f1, float f2){return f1+f2;}float Minus(float f1, float f2){return f1-f2;}float Multiply(float f1, float f2){return f1*f2;}float Divide(float f1, float f2){return f1/f2;}floatMathFunc(float (*p)(float, float), float para1,float para2){return (*p)( para1, para2);}程序运行的结果为:a+b=4.000000a-b=-1.000000a*b=3.750000a/b=0.600000例8-10 利用指向函数的指针,求如下函数在一个区段内的最小值。
本题可以利用指向函数的指针。
虽然所给的函数互不相同,但其在一定区间内求最小值的算法都是通用的。
因此,可以写一个通用的函数float GetMin(float (*p)(float), float fPos1,float fPos2),用于计算不同函数的最小值。
该函数的第一个参数p是一个指向函数的指针,p指向包含一个float型参数的函数。
对应于题目的要求,分别写三个数学函数。
在主函数中,调用GetMin时,第一个参数分别使用上述数学函数的名称,后两个参数传入区间值。
这样,调用三次GetMin即可以求出三个函数在给定区间的最小值。
#include "math.h"float f1(float x){return x*x+2*x+1; /*f1的表达式*/}float f2(float x){return 2*sin(x); /*f2的表达式*/}float f3(float x){return 2*x+1; /*f3的表达式*/}/*p为指向函数的指针,fPos1和fPos2为左右区间的值*/float GetMin(float (*p)(float), float fPos1,float fPos2){float f,t, fMin, fStep=0.01; /* fStep为步长值*//*在fPos1至fPos2的区间内,以fStep为步长,依次比较最小f值*/fMin=(*p)(fPos1);for(f=fPos1;f<=fPos2;f+=fStep){t=(*p)(f);if(t<fMin)fMin=t;}/*返回求出的最小值*/return fMin;}main(){/*直接计算并输出结果*/printf("\nMin value of f1: %f",GetMin(f1,-1,1));printf("\nMin value of f2: %f",GetMin(f2,1,3));printf("\nMin value of f3: %f",GetMin(f3,-1,1));}程序运行的结果为:Min value of f1: 0.000000Min value of f2: 0.282244Min value of f3: -1.000000主函数main调用GetMin函数时,传入了函数名称和区间值。
GetMin函数在计算函数最小值时,根据传入的函数指针p调用相应的函数。
灵活使用指向函数的指针可以提高程序的扩充性。
比如本题,如果要增加条件,计算一个f4(x)=2*logx+1在(0,5)内的最小值,那么我们只需要增加一个f4函数的定义,然后在main 函数中就可以直接进行计算GetMin(f4,0,5),GetMin函数不用进行任何修改。