【IOS 开发学习总结-OC-7.10-★】 objective-c——函数与指针
来源:互联网 发布:威斯敏斯特大学 知乎 编辑:程序博客网 时间:2024/05/17 10:06
指针变量出了可以指向普通的 int变量,float 变量和数组外,还可以指向函数的入口。
用函数指针变量调用函数
定义函数后,C 语言允许定义一个指针变量来指向该函数。
使用函数指针的步骤:
1. 定义函数指针变量。语法格式个为:函数返回值类型(*指针变量名)();
2. 将任何已有的函数入口赋值给函数指针变量。如:pt=avg;
关于上面句子的2点说明:
- C 语言允许任何已有的函数赋值给函数指针变量。所以,同一个函数指针变量在不同时间可指向不同的函数。
- 为函数指针变量赋值时,只需给出函数名即可,无需使用(),也无需传入参数。注意:是将函数入口赋给指针变量,而不是调用函数后将返回的结果赋给函数指针变量。
3. 使用函数指针变量来调用函数。语法格式为:(*函数指针变量)(参数);
示例代码:
#import <Foundation/Foundation.h>int max(int* data , int len){ int max = *data; // 采用指针遍历data数组的元素 for(int* p = data ; p < data + len ; p++) { // 保证max始终存储较大的值 if(*p > max) { max = *p; } } return max;}int avg(int* data , int len){ int sum = 0; // 采用指针遍历data数组的元素 for(int* p = data ; p < data + len ; p++) { // 累加所有数组元素的值 sum += *p; } return sum / len;}int main(int argc , char * argv[]){ @autoreleasepool{ int data[] = {20 , 12 , 8 , 36, 24}; // 定义指向函数的指针变量:fnPt,并将max函数的入口赋给fnPt int (*fnPt)() = max; NSLog(@"最大值:%d" , (*fnPt)(data , 5)); // 将avg函数的入口赋给fnPt fnPt = avg; NSLog(@"最大值:%d" , (*fnPt)(data , 5)); }}
说明:使用函数指针变量可以以增加函数调用的灵活性,这样我们可以将函数指针变量作为参数传入另一个函数。另外,函数指针变量不支持传统指针变量所支持的运算——对2各函数指针变量比较大小,加减一个整数,执行减法没有实际意义。
用函数指针变量作为函数参数★
有时需要定义一个函数,该函数大部分计算逻辑都能确定,但某些处理逻辑暂时无法确定——这需要某些程序代码动态改变,如果希望调用函数时能动态传入这些代码,就需要在函数中定义函数参数,调用该函数时传入不同的函数作为参数,即可动态改变这段代码。
如下程序:
#import <Foundation/Foundation.h>void map(int* data , int len , int (*fn)()){ // 采用指针遍历data数组的元素 for(int* p = data ; p < data + len ; p++) { // 调用fn函数(fn函数是动态传入的) printf("%d , " , (*fn)(*p)); } printf("\n");}int noChange(int val){ return val;}// 定义一个计算平方的函数int square(int val){ return val * val;}// 定义一个计算立方的函数int cube(int val){ return val * val * val;}int main(int argc , char * argv[]){ @autoreleasepool{ int data[] = {20 , 12 , 8 , 36, 24}; // 下面程序代码3次调用map()函数,每次调用时传入不同的函数 map(data , 5 , noChange); NSLog(@"计算数组元素平方"); map(data , 5 , square); NSLog(@"计算数组元素立方"); map(data , 5 , cube); }}
编译运算结果:
20 , 12 , 8 , 36 , 24 ,
计算数组元素平方
400 , 144 , 64 , 1296 , 576 ,
计算数组元素立方
8000 , 1728 , 512 , 46656 , 13824 ,
由此可以看出,定义函数指针变量的形参就可以在在调用函数时动态传入函数,就可以动态地改变被调用函数的部分代码。这种用法,其实就是”命令模式”。
返回指针的函数
函数可以返回普通的数值也可以返回一个指针。
函数返回指针的一种危险情况
由于函数返回的指针只保存了一个地址值,如果该指针指向被调用函数中定义的局部变量,将很危险。因为函数调用结束后,该函数中声明的局部变量所占用的空间已经释放,那么该指针指向的内存单元中的数据将是不确定的。
有2种方式保证函数返回的指针是有效的:
1. 如果函数的指针指向被调用函数中声明的局部变量,该局部变量应用 static 修饰。
2. 让函数返回的指针指向暂时不会被释放的数据。如指向 main() 函数中的变量——只有等到 main() 函数执行完成时,main 函数中的变量才会被释放。因此在 main() 函数结束前,函数返回的指针是安全的。
示例代码:
#import <Foundation/Foundation.h>#define LENGTH 5int* map(int* data ,int (*fn)()){ static int result[LENGTH]; int i = 0; // 采用指针遍历data数组的元素 for(int* p = data; p < data + LENGTH ; p++) { // 调用fn函数(fn函数是动态传入的) result[i++] = (*fn)(*p); } // 返回result的首地址 return result;}int noChange(int val){ return val;}// 定义一个计算平方的函数int square(int val){ return val * val;}// 定义一个计算立方的函数int cube(int val){ return val * val * val;}int main(int argc , char * argv[]){ @autoreleasepool{ int data[] = {20 , 12 , 8 , 36, 24}; // 下面程序代码3次调用map()函数,每次调用时传入不同的函数 int* arr1 = map(data , noChange); for(int i = 0 ; i < LENGTH ; i ++) { printf("%d , " , *(arr1 + i)); } printf("\n"); int* arr2 = map(data , square); for(int i = 0 ; i < LENGTH ; i ++) { printf("%d , " , *(arr2 + i)); } printf("\n"); int* arr3 = map(data , cube); for(int i = 0 ; i < LENGTH ; i ++) { printf("%d , " , *(arr3 + i)); } printf("\n"); }}
由于函数返回的指针指向 map() 函数声明的 result[LENGTH] 数组的首地址,为了保证函数调用完成后,函数返回的指针依然指向有效内存,程序中使用了 static 修饰的result[LENGTH] 数组。
- 【IOS 开发学习总结-OC-7.10-★】 objective-c——函数与指针
- 【IOS 开发学习总结-OC-7.8-★★】 objective-c——指针与数组
- 【IOS 开发学习总结-OC-7.7-★★】 objective-c——指针
- 【IOS 开发学习总结-OC-7.11-★】 objective-c——指针数组和指向指针的指针
- 【IOS 开发学习总结-OC-26】★★★objective-c——foundation 框架之日期与时间
- 【IOS 开发学习总结-OC-19】★★objective-c面向对象之——类别与扩展
- 【IOS 开发学习总结-OC-12】★objective-c面向对象之——合成存取方法与点语法
- 【IOS 开发学习总结-OC-24】★★★objective-c——内存管理
- 【IOS 开发学习总结-OC-17】★★objective-c面向对象之——多态
- 【IOS 开发学习总结-OC-7.6-★】objective-c ——块(Block)
- 【IOS 开发学习总结-OC-9】★ objective-c面向对象之——方法
- 【IOS 开发学习总结-OC-22】★objective-c——使用@try 处理异常
- 【IOS 开发学习总结-OC-18】★★objective-c面向对象之——OC的包装类与对象处理
- 【IOS 开发学习总结-OC-7.5】objective-c 的c语言特性——结构体
- 【IOS 开发学习总结-OC-15】objective-c面向对象之——对象初始化
- 【IOS 开发学习总结-OC-7.4】objective-c与c语言的预处理
- 【IOS 开发学习总结-OC-14】★★★objective-c面向对象之——KVO(键值监听)
- 【IOS 开发学习总结-OC-20】★★★objective-c面向对象——协议(protocol)
- 笔记本外壳材质
- Swift 基本运算符和集合类型
- linux下将eclipse项目转换为gradle项目
- jsp 的四个作用域 :page、request、session和application的区别
- std::string用法总结
- 【IOS 开发学习总结-OC-7.10-★】 objective-c——函数与指针
- CAN控制器-配置过滤器
- 15/9/17学习acttiviti过程笔记
- 【ThinkPHP】文件上传,利用saveRule对上传文件更名
- 内存管理
- 欢迎使用CSDN-markdown编辑器
- LeetCode|Intersection of Two Linked Lists-java
- Linux 运维工程师的十个基本技能点
- xdebug 不需要配置 idekey