http://insswer.iteye.com/blog/1040408
嵌入式C语言笔记03——函数指针,内存陷阱,堆栈
int * function(int);
int *(*fp)(int);
int *ptr;
fp = function; //为函数指针fp赋值,使他指向函数funtion()
ptr=(*fp)(3); //通过函数指针调用函数,与funtion(3)效果一样。
ptr=fp(4); //这也是通过函数指针调用函数,与(*fp)(4)的效果一样
int (*func) (int ,int) //函数指针
int* func (int, int) // 指针函数
int (*array)[array_size] //数组指针
int * array[array_size] //指针数组
2. 函数指针的作用
1) 多态struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*readv) (struct file *, const struct iovec *, unsigned long,
loff_t *);
ssize_t (*writev) (struct file *, const struct iovec *, unsigned long,
loff_t *);
};
结构中的每一个成员名字都对应一个系统调用。
通常情况下的函数调用顺序是用户的函数调用操作系统的函数,上层的函数调用底层的函数,而所谓回调是指由操作系统来调用用户编写的函数。由于操作系统代码在用户代码之前就已经编译完成,因此由操作系统法器的回调一般都必须通过将用户编写函数的函数指针传递给操作系统,再由操作系统实现回调。
3) 多线程
内存陷阱
C语言中对内存的分配方式主要有4种:
2. 动态存储区的注意要点
1) 在差错处理时,忘了释放已分配的动态内存空间,比如下例char *fun(){
char *p,*q;
if((p=malloc(1024))== NULL) return NULL;
if((q=malloc(1024))== NULL) return NULL;
return p;
}
程序中如果p申请成功,q没有申请成功,那么给p的空间将永远消失了。首先看两道道面试题:
变量的定义与声明有啥区别?
首先:变量的定义一定也是变量的初始化,反之则不成立, 在一定的作用域中,变量的声明可以有多个,但是定义只有一个;
-》变量在定义时分配内存空间,同时也可能赋予初值;
-》变量在声明时不会分配内存空间,说明该变量是存在的,指出了该变量的名字和位置。其作用是声明该变量是已在程序后面定义的变量
如: extern int i ; //声明外部变量;<=> extern i ;
如: int i ;//定义变量;
简要说明static的用法?
NO.1 修饰函数,使得函数成为静态函数,在此static并非指存储方式,只是说明该函数的作用域只是局限于本文件;
NO.2 修饰局部变量,成为静态局部变量,存储在静态区,即使函数运行结束,静态变量的值不会被销毁,下次调用该函数时,值仍存在;
NO.3 修饰全局变量,成为静态全局变量,存储在静态区,作用域仅限于变量被定义的文件中,其他文件即使使用extern也无法调用
用关键字const修饰的只读变量与常量的区别:
1. 常量(1 2 3 #define age 2) 是一个静态的值,不需要分配内存,enum类型和#define(注意define不是关键字)宏声明一个常量;变量需要分配内存;
2. const修饰 的 只读变量 不能用来作为定义数组的维数(常量),也不能放在case关键字后面(变量)。
(case 后面只能是 整型 或字符型的 常量 或 常量表达式 )
3. 常量是永远无法改变的,但是只读变量一般无法直接再次赋值,但是可以通过指针改变。
更多参考: const int a = 1; int *pa = &a; a = 2 ;//error
pa = 2;//ok
对于传统CISC处理器对于堆栈的操作有专门的压栈与退栈的指令,并且处理器的硬件会自动完成函数调用与终端处理的返回地址入栈的做。但由于RISC处理器通常采用Load/Store体系,也就是除了Load/Store两类指令外,其他所有的指令都不能访问存储器,处理器的硬件也不会自动地完成堆栈的入栈和出栈操作,比如ARM就需要在最后用MOV PC,LR。
4. 利用堆栈实现局部变量