Day 16 《指针》
(一)指针的反汇编探究
(1)宽度
#include <stdio.h>
void Null()
{
}
void cp()
{
char* c = NULL;
}
void ip()
{
int* i = NULL;
}
void np()
{
char* c = NULL;
short* s = NULL;
int* i = NULL;
}
int main()
{
Null();
cp();
ip();
np();
return 0;
}
(2)声明与赋值
#include <stdio.h>
void Null()
{
}
void test1()
{
char* c ;
short* s;
int * i;
c = (char*)1;
s = (short*)2;
i = (int*)3;
}
void test2()
{
char*** c;
short*** s;
int *** i;
c = (char***)1;
s = (short***)2;
i = (int***)3;
}
void test3()
{
char****** c;
short****** s;
int ****** i;
c = (char******)1;
s = (short******)2;
i = (int******)3;
}
int main()
{
test1();
test2();
test3();
return 0;
}
指针所指向的数据的赋值方式,及其反汇编
带*类型的变量赋值时,只能使用“完整写法”;
带*类型的变量宽度永远是4字节,无论类型是什么,无论有几个*;
多级指针指向的数据的赋值:
这个是6级指针int****** ip,当解析******ip时,解析6次,获取最终指向的变量数据。
注意,此处解析地址时是会报错的,因为ip直接指向i,只需解析1次就够。而此处却多次解析,必然导致内存访问异常之类的错误。
(3)++ –
void test()
{
char c = 'a';
int i = 1;
char* cp = &c;
int* ip = &i;
int arr[5] = { 1,2,3,4,5 };
int* ap = arr;
int* app = &arr;
++cp;
++(*cp);
--ip;
--(*ip);
++ap;
}
类型变量的自增或自减,相当于指向地址的偏移。其偏移量跟其指针的数据类型有关,如果是char类型的变量自增,则其值为原值+1;如果是int*类型的变量自减,则其值为原值-4;
(5)加上/减去 一个整数
void test()
{
char c = 'a';
int i = 1;
char* cp = &c;
int* ip = &i;
cp+=5;
ip -= 3;
}
*类型变量加上或减去一个整数,相当于指向地址的偏移。其偏移量跟其指针的数据类型有关,如果是char*类型+5,则其值为原值+5;如果是int*类型的变量减3,则其值为原值-12(即-3*4);
注意,带*类型的变量可以加减一个整数,但是不能乘或者除。
(6)求差值
void test()
{
char c1 = 'a';
char c2 = 'b';
int i1 = 1;
int i2 = 2;
char* cp1 = &c1;
char* cp2 = &c2;
int* ip1 = &i1;
int* ip2 = &i2;
int x = cp1 - cp2;
int y = ip1 - ip2;
}
两个同类型的一级指针相减,相当于其所指向的两个数据之间的偏移,偏移值为其类型的整数倍。
如果两个内存之间相差12个字节,如果它们类型为int,则其差为3(即相差3个int);如果它们的类型为char,则其差为12(即相差12个char);
注意:不能相加,只能相减;(相加没意义)
相减的结果要除以去掉一个*的数据的宽度;
(7)比较
带*的变量,如果类型相同,可以做大小的比较。比较的只是地址的大小。
(二)练习
(1)char类型占几个字节?char*占几个字节?int***占几个字节?**
答: char类型占1个字节;char*类型占4个字节;int*****占4个字节。
(2)char** arr[10]占多少个字节?
答: 占40(10*4)个字节。
(3)自定义结构体类型的指针
struct Student
{
int x;
int y;
};
void Fun1()
{
struct Student**** s;
s = (struct Student****)100;
s++; //1.求s值
s = s + 2; //2.求s值
s = s - 3; //3.求s值
}
void Fun2()
{
struct Student**** s1;
struct Student**** s2;
int x;
s1 = (struct Student****)200;
s2 = (struct Student****)100;
x = s1 - s2; //4.求x值
}
void Fun3()
{
struct Student* s;
s = (struct Student*)100;
s++; //5.求s值
s = s + 2; //6.求s值
s = s - 3; //7.求s值
}
void Fun4()
{
struct Student* s1;
struct Student* s2;
int x;
s1 = (struct Student*)200;
s2 = (struct Student*)100;
x = s1 - s2; //8.求x值
}
答: (1)104 (2)112 (3)100
(4)25
(5)108 (6)124 (7)100
(8)12
2017/5/31 12:23:01
Day 17 《类型转换与指针的进阶》
(一)类型转换
#include <stdio.h>
struct Student
{
int id;
int level;
};
void Test()
{
int x = 10;
char y = (char)x;
}
void Test2()
{
char* x;
int * y;
x = (char*)10;
y = (int*)x;
}
void Test3()
{
int* x;
struct Student* y;
x = (int*)10;
y = (struct Student*)x;
}
void Test4()
{
char* x;
char** y;
x = (char*)10;
y = (char**)x;
}
int main()
{
Test();
Test2();
Test3();
Test4();
return 0;
}
(二)&符号使用与“带*类型”的特性探测(求值)
1.取地址符&
&是地址符,类型是该变量的类型+” * ” ,任何变量都可以使用&来取地址,但不能用在常量上;
例如:
int i = 10;
int* p = &i;
那么 &i 的类型为 int*;
void Test()
{
char*** a = (char***)10;
char c = 'a';
int i = 30;
int* p = &i;
a = &c;
}
int x = 10;
void Test2()
{
int* p = &x;
}
2.用于取值(解析地址)的运算符” * ”
void Test()
{
int* px = (int*)10;
int ** px2 = (int**)11;
int *** px3 = (int***)12;
int **** px4 = (int****)13;
int x = 10;
px = &x;
char x1 = *px;
}
(三)使用指针操作数组
void Test()
{
char arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
char* p = &arr[0];
char* p2 = arr;
}
void Test2()
{
char arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
char* p = arr;
for (int i = 0; i < 10; i++)
{
*(p + i) = i * 2;
}
for (int k = 0; k < 10; k++)
{
printf("%d\n", *(p + k));
}
}
void Test3()
{
char arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
short* p = arr;
for (int i = 0; i < 10; i++)
{
*(p + i) = i * 2;
}
for (int k = 0; k < 10; k++)
{
printf("%d\n", *(p + k));
}
}
void Test4()
{
char arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;
for (int i = 0; i < 10; i++)
{
*(p + i) = i * 2;
}
for (int k = 0; k < 10; k++)
{
printf("%d\n", *(p + k));
}
}
当指针类型为 short* 或 int* 时,指针的偏移为 2字节 和 4字节。因为带*的类型加上或减去一个整数时,会根据其类型+1(char*) 、+2(short*) 、+4(int*);
当short*或int*类型变量指向char数组时,再运行中很可能会出错。
*(p+i)= p[i]
(四)练习
//1. 列出每一行的反汇编代码
void Fun1()
{
char a = 10;
short b = 20;
int c = 30;
char* pa = &a;
short* pb = &b;
int* pc = &c;
char** ppa = &pa;
short** ppb = &pb;
int** ppc = &pc;
}
答:
mov byte ptr[ebp-4], 10
mov word ptr[ebp-8], 20
mov dword ptr[ebp-Ch], 30
lea eax,[ebp-4]
mov dword ptr [ebp-14h],eax
lea eax,[ebp-8]
mov dword ptr [ebp-18h],eax
lea eax,[ebp-Ch]
mov dword ptr [ebp-1Ch],eax
lea eax,[ebp-14h]
mov dword ptr [ebp-24h],eax
lea eax,[ebp-18h]
mov dword ptr [ebp-28h],eax
lea eax,[ebp-1Ch]
mov dword ptr [ebp-2Ch],eax
//2. 列出每一行的反汇编代码
void Fun2()
{
int p = 10;
int ******* p7;
int ****** p6;
int ***** p5;
int **** p4;
int *** p3;
int ** p2;
int * p1;
p1 = &p;
p2 = &p1;
p3 = &p2;
p4 = &p3;
p5 = &p4;
p6 = &p5;
p7 = &p6;
}
答:
mov dword ptr [ebp-4],0Ah
lea eax,[ebp-4]
mov dword ptr [ebp-8],eax
lea eax,[ebp-8]
mov dword ptr [ebp-Ch],eax
lea eax,[ebp-Ch]
mov dword ptr [ebp-10h],eax
lea eax,[ebp-10h]
mov dword ptr [ebp-14h],eax
lea eax,[ebp-14h]
mov dword ptr [ebp-14h],eax
lea eax,[ebp-18h]
mov dword ptr [ebp-18h],eax
lea eax,[ebp-1Ch]
mov dword ptr [ebp-1Ch],eax
//3. 列出反汇编语句
void Fun3()
{
int x, y;
int* px1;
int** px2;
int*** px3;
int**** px4;
int***** px5;
x = 10;
px1 = &x;
px2 = &px1;
px3 = &px2;
px4 = &px3;
px5 = &px4;
y = *(*(*(*(*(px5)))));
}
答:
mov dword ptr [ebp-4],0Ah
lea eax,[ebp-4]
mov dword ptr [ebp-Ch],eax
lea eax,[ebp-Ch]
mov dword ptr [ebp-10h],eax
lea eax,[ebp-10h]
mov dword ptr [ebp-14h],eax
lea eax,[ebp-14h]
mov dword ptr [ebp-18h],eax
lea eax,[ebp-18h]
mov dword ptr [ebp-1Ch],eax
mov eax,dword ptr [ebp-1Ch]
mov ecx,dword ptr [eax]
mov edx,dword ptr [ecx]
mov eax,dword ptr [edx]
mov ecx,dword ptr [eax]
mov edx,dword ptr [ecx]
mov dword ptr [ebp-8],edx
//4. 完成代码,实现数组值的互换
void Fun4()
{
int arr[5] = { 1,2,3,4,5 };
//..此处添加代码,使用指针,将数组的值倒置
for (int k =0;k<5;++k)
{
printf("%d\n", *(p + k));
}
}
答:
void Fun4()
{
int arr[5] = { 1,2,3,4,5 };
//..此处添加代码,使用指针,将数组的值倒置
int* p =arr;
for(int i = 0; i<(5/2); i++)
{
int t = *(p+i);
*(p+i) = *(p+4-i);
*(p+4-i) = t;
}
for (int k =0;k<5;++k)
{
printf("%d\n", *(p + k));
}
}
2017/6/1 16:56:06
Day 18 《数据搜索》
(一)搜索数据
- 数组作为参数
- 通过char指针遍历数据
- 通过short指针遍历数据
- 通过int指针遍历数据
练习:这一堆数据中存储了角色的血量信息,假设血值的类型为int类型,值为100(10进制)
请列出所有可能的值以及该值对应的地址;
#include<stdio.h>
char data[100] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x00,0x20,0x10,0x03,0x03,0x0c,0x00,0x00,0x33,0x00,
0x00,0x33,0x00,0x47,0x0c,0x0e,0x00,0x0d,0x00,0x11,
0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xaa,0x00,
0x00,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x02,0x00,0x74,0x0f,0x41,0x00,0x00,0x00,
0x01,0x01,0x02,0x00,0x05,0x00,0x00,0x00,0x0a,0x00,
0x00,0x02,0x74,0x0f,0x41,0x00,0x06,0x08,0x00,0x00,
0x00,0x00,0x00,0x64,0x00,0x0f,0x00,0x00,0x0d,0x00,
0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00
};
//假设该数据排列是由地位到高位
void FindBloodAddr(char* p[])
{
int k = 0;
memset(p, 0, sizeof(char*) * 10);
for (int i = 0; i < 100-3;)
{
if (data[i] == 0x64)
{
if (data[i + 1] == 0x00 && data[i + 2] == 0x00 && data[i + 3] == 0x00)
{
p[k++] = &data[i];
i += 4;
continue;
}
i++;
}
else
{
++i;
}
}
}
int main()
{
char* p[10];
FindBloodAddr(p);
return 0;
}
(二)字符相关
1.字符数组与字符串及常量区
void Fun()
{
char a_name[10] = { 'w', 'w', 'w' };
char* s_name = "www";
char as_name[] = "www2";
}
指针指向的字符串存于常量区,该字符串指针存储了对应字符串的指针;
字符串数组使用缺省的方式初始化时,未赋值的部分会以0填充;
未指定大小的字符数组使用字符串初始化时,会在其栈中开辟出字符串大小+1的空间用于存储数据,并将字符串常量的值复制到数组中,结尾为0;
2.常见字符串操作与指针函数
1. int strlen(char* s);
返回值是字符串s的长度,不包括结束符‘/0’;
char* strcpy(char* dest,char* src);
复制字符串src到dest中,返回指针为dest的值;char* strcat(char* dest,char* src);
将字符串src添加到dest尾部,返回指针dest的值;int strcmp(char* sl,char* s2);
一样返回0,不一样返回1;具体代码如下:
int strlen(char* s)
{
int ret = 0;
while (*s != 0)
{
ret++;
s++;
}
return ret;
}
char* strcpy(char* dest, char* src)
{
char* ret = dest;
while ((*dest++) = (*src++));
return ret;
}
char* strcat(char* dest, char* src)
{
char* ret = dest;
while (*dest!=0)
{
dest++;
}
while ((*dest++) = (*src++));
return ret;
}
int strcmp(char* s1, char* s2)
{
while (*s1++ == *s2++)
{
if ((!*s2)&&(!*s1))
return 0;
}
return 1;
}
指针函数就是一个返回值是个*类型的函数
(三)练习
char gameData[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09,
0x00,0x20,0x10,0x03,0x03,0x0c,0x00,0x00,0x44,0x00,
0x00,0x33,0x00,0x47,0x0c,0x0e,0x00,0x0d,0x00,0x11,
0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xaa,0x00,
0x00,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x02,0x00,0x74,0x0f,0x41,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0a,0x00,
0x00,0x02,0x57,0x4f,0x57,0x00,0x06,0x08,0x00,0x00,
0x00,0x00,0x00,0x64,0x00,0x0f,0x00,0x00,0x0d,0x00,
0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00
};
1.编写函数,返回角色名字信息的地址,如果没有返回0;
char* FindRoleNameAddr(char* pData, char* pRoleName)
{
char* ret = 0;
int i = 100;
while(i--)
{
while (*(ret=pData++) == *pRoleName)
{
char *s1 = ret, *s2 = pRoleName;
while (*s1++ == *s2++)
{
if (!*s2)
return ret;
}
}
}
return 0;
}
int main()
{
FindRoleNameAddr(gameData, "WOW");
return 0;
}
2.编写函数,遍历上面数据中所有角色名字;(假设只允许出现字母)
void printRoleName(char* pData)
{
int i = 100;
while (i--)
{
while ((*pData>'A'&&*pData<'Z') || (*pData>'a'&&*pData<'z'))
{
printf("%c",*pData++);
}
pData++;
printf(" ");
}
}
2017/6/2 11:27:32
Day 19 《指针数组与结构体指针》
(一)指针数组
void Test1()
{
int *arr[5] = { 0 };
arr[0] = (int*)10;
arr[1] = (int*)10;
arr[2] = (int*)10;
arr[3] = (int*)10;
arr[4] = (int*)10;
char* arr2[5] = { 0 };
arr2[0] = (char*)1;
arr2[1] = (char*)2;
arr2[2] = (char*)3;
arr2[3] = (char*)4;
arr2[4] = (char*)5;
}
void Test2()
{
char a1 = 'A';
char a2 = 'B';
char a3 = 'C';
char a4 = 'D';
char a5 = 'E';
char* p1 = &a1;
char* p2 = &a2;
char* p3 = &a3;
char* p4 = &a4;
char* p5 = &a5;
char* arr2[5] = { p1,p2,p3,p4,p5 };
}
void Test3()
{
char* p1 = "if";
char* p2 = "for";
char* p3 = "while";
char* p4 = "switch";
char* keyword[] = { p1,p2,p3,p4 };
}
注意:
此处数组keyword存储的是p1p2p3p4的值,而不是其地址。
(二)结构体指针
struct Arg1
{
int a;
int b;
int c;
};
void test1()
{
struct Arg1*pArg;
pArg = (struct Arg1*)100;
pArg++;
}
struct Arg2
{
int a;
char b;
short c;
};
void test2()
{
struct Arg2 s;
s.a = 10;
s.b = 20;
s.c = 30;
struct Arg2* px = &s;
px->a = 100;
px->b = 200;
px->c = 300;
}
(三)练习
1.创建一个int* arr[5]数组,并为数组赋值(使用&)
void Fun1()
{
int* arr[5];
int a1 = 10;
int a2 = 20;
int a3 = 30;
int a4 = 40;
int a5 = 50;
arr[0] = &a1;
arr[1] = &a2;
arr[2] = &a3;
arr[3] = &a4;
arr[4] = &a5;
}
2.创建一个字符指针数组,存储所有的C的关键词,并全部打印出来
void Fun2()
{
char* keyword[] = {
"auto","double","int","struct","break","else", "long" ,"switch",
"case" ,"enum" ,"register", "typedef" ,"char", "extern" ,"return" ,"union",
"const", "float", "short", "unsigned", "continue", "for", "signed", "void",
"default", "goto", "sizeof", "volatile", "do", "if", "while", "static" };
for(int i = 0; i < 32 ; i++)
{
printf("%s, ", keyword[i]);
}
}
3.查找这些数据中,有几个id=1 level=8的结构体信息
void Fun3()
{
char data[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09,
0x00,0x20,0x10,0x03,0x03,0x0c,0x00,0x00,0x44,0x00,
0x00,0x33,0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xaa,0x00,
0x00,0x00,0x64,0x01,0x00,0x00,0x00,0x08,0x00,0x00,
0x00,0x00,0x02,0x00,0x74,0x0f,0x41,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0a,0x00,
0x00,0x02,0x57,0x4f,0x57,0x00,0x06,0x08,0x00,0x00,
0x00,0x00,0x00,0x64,0x00,0x0f,0x00,0x00,0x00,0x00,
0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00 };
int count = 0;
Player _target = { 1,8 };
char *_data = data;
char* ptarget = &_target;
int i = 100;
while (i--)
{
if (*_data++ == *ptarget)
{
char *s1 = _data, *s2 = ptarget + 1;
int j = sizeof(Player) - 1;
while (*s1++ == *s2++)
{
j--;
if (!j)
{
count++;
break;
}
}
}
}
}
Day 19 《多级指针》
(一)多级指针
int main()
{
char* p1 = 100;
char** p2 = 200;
char*** p3 = 300;
char**** p4 = 400;
char***** p5 = 500;
char****** p6 = 600;
char******* p7 = 700;
printf("%d\n", *p1);
看到带*的,只需要想到:宽度、++、–、差值、+整数、比较 就行了。
1.多级指针
*p1 = *(p1 + 0);
printf("%d\n", *(p1 + 0));
*(p1 + 0) = p1[0];
printf("%d %d\n", *(p1 + 0), p1[0]);
printf("%d %d\n", *(p1 + 2), p1[2]);
printf("%d\n", *p2);
printf("%d\n", *(*p2));
printf("%d %d\n", *(*(p2 + 0)), *(*(p2 + 0) + 0));
printf("%d\n", *(*(p2 + 1)));
printf("%d\n", *(*(p2 + 1) + 1));
printf("%d\n", *(*(p2 + 2) + 3));
printf("%d %d\n", *(*(p2 + 0) + 0), p2[0][0]);
printf("%d\n", *p3);
printf("%d\n", *(*p3));
printf("%d\n", *(*(*p3)));
printf("%d %d\n", *(*(*p3)), *(*(*(p3 + 0) + 0) + 0));
printf("%d\n", *(*(*(p3 + 1) + 2) + 3));
printf("%d %d\n", *(*(*(p3 + 1) + 2) + 3),p3[1][2][3]);
return 0;
}
总结:
*(p+i) = p[i]
((p+i)+k) = p[i][k]
((*(p+i)+k)+m) = p[i][k][m]
((((*(p+i)+k)+m)+w)+t) = p[i][k][m][w][t]
*() 与 [] 可以互换
指针函数:本质就是函数,返回值是个指针
指针数组,本质是数组,保存数值为指针
int main()
{
int(*px)[5];
//宽度:4
printf("%d\n", sizeof(px));
//赋值
px = (int(*)[5])10;
//++
printf("%d\n", px);
px++;
printf("%d\n", px);
return 0;
}
2.指针数组
int main()
{
int arr[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
int(*px)[2];
px = (int(*)[2])arr;
printf("%d\n", *(*px)); //1
printf("%d\n", *(*(px + 0) + 0)); //1
printf("%d\n", *(*(px + 1) + 1)); //4
printf("%d\n", *(*(px + 3) + 3)); //10
printf("%d\n", px[3][3]); //10
return 0;
}
px 和 *px 两个值是一样的,类型是不同的。
*(p+1)[2]是否一定等于p[1][2]呢?
int main()
{
int arr[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
int(*p)[2] = arr;
int i = *(p + 1)[2];
int j = p[1][2];
return 0;
}
指针不是固定的,没有固定的指向格式,想怎么用就怎么用。
数组指针
int main()
{
char code[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09,
0x00,0x20,0x10,0x03,0x03,0x0c,0x00,0x00,0x44,0x00,
0x00,0x33,0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xaa,0x00,
0x00,0x00,0x64,0x01,0x00,0x00,0x00,0x08,0x00,0x00,
0x00,0x00,0x02,0x00,0x74,0x0f,0x41,0x00,0x00,0x00,
0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0a,0x00,
0x00,0x02,0x57,0x4f,0x57,0x00,0x06,0x08,0x00,0x00,
0x00,0x00,0x00,0x64,0x00,0x0f,0x00,0x00,0x00,0x00,
0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00 };
//1.一维数组指针
char(*px1)[5];
px1 = (char(*)[5])code;
printf("%x\n", *(*(px1 + 2) + 2)); //10
int(*px2)[5];
px2 = (int(*)[5])code;
printf("%x\n", *(*(px2 + 2) + 2)); //0
//2.二维数组指针
char(*py1)[2][3];
py1 = (char(*)[2][3])code;
printf("%x\n", *(*(*(py1)))); //0
int(*py2)[2][3];
py2 = (int(*)[2][3])code;
printf("%x\n", *(*(*(py2+2)+2)+2));//64000000
//3.三维数组指针
char(*pz1)[2][3][2];
pz1 = (char(*)[2][3][2])code;
printf("%x\n", *(*(*(*(pz1 + 2) + 2) + 2) + 2));//64
char(*pz2)[2][3][2];
pz2 = (char(*)[2][3][2])code;
printf("%x\n", *(*(*(*(pz2 + 2) + 2) + 2) + 2));//64
ret
3.函数指针
int Fun(int x, int y)
{
return x + y;
}
int main()
{
int(*pFun)(int, int);
pFun = (int(*)(int, int))Fun;
int i = pFun(1, 2);
return 0;
}
函数指针不能做++、 –、 +整数等运算,比较大小可以。
动态链接库的加载,就是通过函数指针来实现的。
4.练习
1. 下列说法是否正确?为什么?
指针的指针,就是指向指针的指针;
结构指针,就是指向结构体的指针;
数组指针,就是指向数组的指针;
函数指针,就是指向函数的指针;
答:说法不对,指针的指向不是固定的。什么类型的指针,区别在于解析地址以及寻址的方式上不同。
将一个函数存储到数据区,通过指针进行访问。
char data[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x09, 0x00,0x20,0x10,0x03,0x03,0x0c,0x00,0x00,0x44,0x00, 0x00,0x33,0x00,0x47,0x0c,0x0e,0x00,0x0d,0x00,0x11, 0x00,0x00,0x00,0x02,0x64,0x00,0x00,0x00,0xaa,0x00, 0x00,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x02,0x00,0x74,0x0f,0x41,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0a,0x00, 0x00,0x02,0x74,0x0f,0x41,0x00,0x06,0x08,0x00,0x00, 0x00,0x00,0x00,0x64,0x00,0x0f,0x00,0x00,0x0d,0x00, 0x00,0x00,0x23,0x00,0x00,0x64,0x00,0x00,0x64,0x00 }; int(*px)[2]= data; int i = *(*(px + 0) + 0); int j = *(*(px + 1) + 0); int k = *(*(px + 2) + 3); int(*py)[2][3]= data; i = *(*(*(py + 1) + 2) + 3); char(*pz)[2] = data; j = *(*(pz + 2) + 3);
说出结果:
((px + 0) + 0); //0x03020100
((px + 1) + 0); //0x20000907
((px + 2) + 3); //0x00001100
*(*(*(py + 1) + 2) + 3); //0x00000001
*(*(pz + 2) + 3); //0x07