一.二维数组
1.在栈上创建数组
一维数组:int *p=(int []){0};
二维数组:int (*px)[4]=(int [][4]){0};
三维数组:int (*py)[3][4]=(int [][3][4]){0};
2.堆上分配二维数组(地址不连续)
void main2()
{
int **pp = calloc(3, 4);//分配指针数组
for (int i = 0; i < 3;i++)
{
pp[i] = malloc(4 * sizeof(int));//每个指针分配内存
}
int num = 0;
for (int i = 0; i < 3;i++)
{
for (int j = 0; j < 4;j++)
{
printf("%4d",pp[i][j]=num++ );// *( *(pp+i)+j) pp[i][j]
//*(pp+i) ==pp[i] pp+i == &pp[i]
}
printf("\n");
}
for (int i = 0; i < 3;i++)//先释放块
{
free(pp[i]);
}
free( pp);//再释放指针数组
system("pause");
}
3.堆上分配二维数组(地址连续)
void main4()
{
int(*p)[4] = malloc(sizeof(int)* 12);//连续
int num = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%4d", p[i][j] = num++);//
}
printf("\n");
}
free(p);
system("pause");
}
二.函数指针
1.函数指针的非法调用
不可以在一个进程中调用另一个进程的函数,但可以用dll函数调用另一个进程的函数,实现非法调用
<span style="font-size:24px;">_declspec(dllexport) void main()
{
void (*p)()=0x10510b9;//函数指针,地址为要调用函数的地址
p();//调用
}</span>
2.函数指针变量,在数据区,但是存储了代码区的地址,函数在代码区
四.函数指针强化
1.函数指针用法
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int divv(int a, int b)
{
return a /b;
}
int getmax(int a, int b)
{
return a > b ? a : b;
}
int getmin(int a, int b)
{
return a < b ? a : b;
}
void op( int (*p)(int,int) ,int a,int b )
{
printf("%d\n", p(a, b));
}
void main2()
{
op(add, 1, 2);
op(divv, 1, 2);
system("pause");
}
2.返回函数时的用法
void main1()
{
int(*p1)(int a, int b)=add(1,2);
int(*p2)(int, int)=add;//参数名可以省略
p1(1, 2);
//p1++; 函数指针没有自增,自建
//p2++;
//p3 + n;
}
//int(*p)(int, int)函数指针
//int(*)(int, int) 函数指针类型
//int(* get() )(int, int) //一个函数,参数为空,返回值是一个函数指针
//
// int( * get(int (*y)(int,int),double) )(int, int)
// int( * )(int, int) //函数指针类型
// get( int (*y)(int,int) , double) 整体
int(* getop())(int, int)
{
return add;
}
void main()
{
printf("%d", getop()(1, 2));
system("pause");
}
五.函数指针数组与二级函数指针
1.动态函数指针用法
void main3()
{
int(**pp)(int, int) = malloc(sizeof(int(*)(int, int)) * 4);//堆区
*pp = add;
*(pp + 1) = sub;
*(pp + 2) = mul;
*(pp + 3) = divv;
for (int i = 0; i < 4; i++)
{
// printf("%d\n", pp[i](100, 10));
printf("%d\n", (*(pp + i))(100, 10));
}
system("pause");
}
2.int (*p)[5]; 指向数组的指针,占四个字节
int *p[5];是一个数组,每一个元素是一个指针
七.函数指针数组与多线程
1.多线程异步执行多个函数
void run1(void*p)
{
MessageBoxA(0, "1", "1", 0);
}
void run2(void*p)
{
MessageBoxA(0, "2", "2", 0);
}
void run3(void*p)
{
MessageBoxA(0, "3", "3", 0);
}
void main()
{
//run1(NULL);
//run2(NULL);
//run3(NULL);
//for (int i = 0; i < 3;i++)
//{
// HANDLE hd= _beginthread(run1, 0, NULL);
// //WaitForSingleObject(hd, INFINITE);//无限等待
// WaitForSingleObject(hd, 3000);//3000等待3秒
//}
//HANDLE hd[3] = { 0 };
HANDLE *hd = malloc(12);
//void(*pfun[3])(void*p) = { run1, run2, run3 };//函数指针数组
void(**pfun)(void*p) = (void(*[3])(void*p)){ run1, run2, run3 };
for (int i = 0; i < 3;i++)
{
hd[i] = _beginthread(pfun[i], 0, NULL);
}
//TRUE等待所有线程,fause等待一个
WaitForMultipleObjects(3, hd, FALSE, INFINITE);//等待多个线程结束
//
//主线程,控制全局,
//system("pause");
}
//线程可以同步,也可以异步
//WaitForSingleObject(hd, 3000);//3000等待3秒
//主线程,控制全局
//WaitForMultipleObjects(3, hd, TRUE, INFINITE);//
八.栈内存分配
int *p=alloca(sizeof(int)* 10);
alloca分配内存后自动释放内存
十.函数返回值副本机制
1.函数返回指针的时候,不可以返回指针指向栈区的内存,要获取指针函数返回值,该函数必须在堆上开辟内存
int * rungetmin()
{
int *p = calloc(10, sizeof(int));//不会自动释放
time_t ts;
unsigned int num = time(&ts);//地址改变数据
srand(num);
for (int i = 0; i < 10;i++)
{
p[i] = rand() % 100;
printf("\n%d", p[i]);
}
int imin = 0;//下标
for (int i = 1; i < 10;i++)
{
if (p[i]<p[imin])
{
imin = i;//记录下标
}
}
// p + imin &p[imin]
//*(p+imin) p[imin]
return p + imin;
}
void main10()
{
printf("最小的是%d", *rungetmin());
system("pause");
}
2.普通在栈上的函数返回值有副本机制,存储在cpu,所以不能对其取地址等操作