int add(int i,int j)的类型为 int(int,int)
typedef type name(parameter list)
例如:
typedef int f(int ,int);
typedef void p(int);
FuncType* pointor;
type(*pointor)(parameter list)
——pointor 为函数指针名
——type 为所指的函数的返回类型
——parameter list 为所指函数的参数类型列表
tips:
面试小问题:
如何使用C语言直接跳转到某个固定的地址开始执行?
通过函数指针,因为一个函数名,即为函数的入口的地址,函数指针指向的其实就是一个地址。
示例:
#include
typedef int(Func)(int);
int test(int n)
{
return n*n;
}
void fun()
{
printf("Call fun()\n");
}
int main(int argc,char*argv[])
{
Func* pt=test;
void(*pf)()=NULL;
if(argc>1)
{
pf=0x400576; //函数指针指向固定地址
printf(" void(*pf)()=0x400576\n");
}
else
{
pf=fun;
printf(" void(*pf)()=fun\n");
}
printf("pf = %p\n", pf);
printf("f = %p\n", fun);
printf("&f = %p\n", &fun);
pf();
(*pf)();
printf("Call function point:%d\n",pt(6));
return 0;
}
示例:
#include
typedef void(*Attack)(int );
void knife(int n)
{
for(int i=0;i<n;i++)
{
printf("Boss attack by knife\n");
}
printf("Boss lose %d blood\n",n);
}
void jian(int n)
{
for(int i=0;i<n*3;i++)
{
printf("Boss attack by jian\n");
}
printf("Boss lose %d blood\n",n*3);
}
void gun(int n)
{
for(int i=0;i<n*5;i++)
{
printf("Boss attack by gun\n");
}
printf("Boss lose %d blood\n",n*5);
}
void fight(Attack at,int n)
{
at(n);
}
int main()
{
fight(gun,1);
fight(jian,1);
fight(knife,1);
return 0;
}
示例:
#include
int main()
{
int (*p1)(int*, int (*f)(int*));
// p1是一个函数指针,返回值为int,参数:(int *,和一个参数为int * ,返回值为int 类型的函数指针。)
int (*p2[5])(int*);
// p2是一个数组,有五个元素为指针,指向函数,函数的返回值为int ,参数为int *
int (*(*p3)[5])(int*);
// p3是一个数组指针,指向的数组有5个元素,这5个元素为函数指针,指向的函数类型为int(int *)
int*(*(*p4)(int*))(int*);
//p4是一个指针,函数指针,参数为int*类型,返回值为int*(int *)
int (*(*p5)(int*))[5];
//p5为指针,函数指针,参数为int *,返回值为指针,指向数组,指向数组的类型为int[5]
return 0;
}
简化示例:
int (*(*p5)(int*))[5];
可以简化为:
typedef int (ArrayType)[5]
typedef ArrarType*(FuncType)(int *)
FuncType*p5; //和上述p5指针等价
void* malloc(size_t size);
void free(void* pointer);
tips
//mleak.h
#ifndef _MLEAK_H_
#define _MLEAK_H_
#include
#define MALLOC(n) mallocEx(n, __FILE__, __LINE__)
#define FREE(p) freeEx(p)
void* mallocEx(size_t n, const char* file, const line);
void freeEx(void* p);
void PRINT_LEAK_INFO();
#endif
//mleak.c
#include "mleak.h"
#define SIZE 256
/* 动态内存申请参数结构体 */
typedef struct
{
void* pointer;
int size;
const char* file;
int line;
} MItem;
static MItem g_record[SIZE]; /* 记录动态内存申请的操作 */
void* mallocEx(size_t n, const char* file, const line)
{
void* ret = malloc(n); /* 动态内存申请 */
if( ret != NULL )
{
int i = 0;
/* 遍历全局数组,记录此次操作 */
for(i=0; i<SIZE; i++)
{
/* 查找位置 */
if( g_record[i].pointer == NULL )
{
g_record[i].pointer = ret;
g_record[i].size = n;
g_record[i].file = file;
g_record[i].line = line;
break;
}
}
}
return ret;
}
void freeEx(void* p)
{
if( p != NULL )
{
int i = 0;
/* 遍历全局数组,释放内存空间,并清除操作记录 */
for(i=0; i<SIZE; i++)
{
if( g_record[i].pointer == p )
{
g_record[i].pointer = NULL;
g_record[i].size = 0;
g_record[i].file = NULL;
g_record[i].line = 0;
free(p);
break;
}
}
}
}
void PRINT_LEAK_INFO()
{
int i = 0;
printf("Potential Memory Leak Info:\n");
/* 遍历全局数组,打印未释放的空间记录 */
for(i=0; i<SIZE; i++)
{
if( g_record[i].pointer != NULL )
{
printf("Address: %p, size:%d, Location: %s:%d\n", g_record[i].pointer, g_record[i].size, g_record[i].file, g_record[i].line);
}
}
}
#include
#include "mleak.h"
void f()
{
MALLOC(100);
}
int main()
{
int* p = (int*)MALLOC(3 * sizeof(int));
f();
p[0] = 1;
p[1] = 2;
p[2] = 3;
FREE(p);
PRINT_LEAK_INFO();
return 0;
}
检测出有100字节的内存没有释放。
void *calloc(size_t num,size_t size);
void *relloc(void * pointer,size_t new_size);
示例:
#include
#include
#define SIZE 5
int main()
{
int i = 0;
int* pI = (int*)malloc(SIZE * sizeof(int));
short* pS = (short*)calloc(SIZE, sizeof(short));
for(i=0; i<SIZE; i++)
{
printf("pI[%d] = %d, pS[%d] = %d\n", i, pI[i], i, pS[i]);
}
printf("Before: pI = %p\n", pI);
pI = (int*)realloc(pI, 2 * SIZE * sizeof(int));
printf("After: pI = %p\n", pI);
for(i=0; i<10; i++)
{
printf("pI[%d] = %d\n", i, pI[i]);
}
free(pI);
free(pS);
return 0;
}
#include
int* g()
{
int a[10] = {
0};
return a;
}
void f()
{
int* pointer = g();
int b[10]={
0,1,2,3,4,5,6,7,8,9};
/*for(int i=0;i<10;i++)
{
b[i]=pointer[i];
}
*/
for(int i=0;i<10;i++)
{
printf("%d\n",pointer[i]);
}
}
int main()
{
f();
return 0;
}
问题: 为什么有了栈还需要堆呢?
栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,如:局部数组
示例:验证静态存储区的存在
#include
int g_v = 1;
static int g_vs = 2;
void f()
{
static int g_vl = 3;
printf("%p\n", &g_vl);
}
int main()
{
printf("%p\n", &g_v);
printf("%p\n", &g_vs);
f();
return 0;
}
最后可以发现:它们地址是连在一起,所以可以判断静态存储区的存在。
栈,堆,静态存储区是程序中三个基本的数据存储区
——栈区主要用于函数调用的使用
——堆区主要用于内存的动态申请和归还
——静态存储区用于保存全局变量和静态变量
例如:浏览器的多开,浏览器为一个程序,当双击之后被操作系统加载,成为了进程。多开对应多个进程.