- 指针 64位中 占8个(64Bit)字节
- 编译器决定了指针不能做乘法和除法
- 指针的运算结果,由它所指向的数据类型的宽度。决定!(即去掉一个星看这个数据类型)
- 数据类型可以强制转换的,结构体和基本类型不可转换。任何变量都可以使用&(取地址符)
int* a;
a = (int *)100;
a++;
printf("%d",a);
打印结果 104
char* a;
a = (char *)100;
a++;
printf("%d",a);
打印结果 101
char** a;
a = (char **)100;
a++;
printf("%d",a);
打印结果 108
指针加减法所得结果需要除以指向类型的宽度(int类型的宽度是4)
int * a;
a = (int*)100;
int * b;
b = (int *)200;
int x = a - b;
printf("%d",x);
打印结果 -25
指针的反汇编形式(图1 为汇编详解)
高级代码:
int *a;
int b = 13;
a = &b;
汇编源码
0x100c068c4 <+0>: sub sp, sp, #0x20 ; =0x20
栈空间拉伸32个字节(即0x16b5f39a0-->0x16b5f3980)
0x100c068c8 <+4>: stp x29, x30, [sp, #0x10]
x29,x30的值写入sp偏移0x10的栈空间
0x100c068cc <+8>: add x29, sp, #0x10 ; =0x10
x29指向此时的栈底即(0x16b5f3990)
0x100c068d0 <+12>: add x8, sp, #0x4 ; =0x4
sp偏移0x4(0x16b5f3984)的地址给x8
0x100c068d4 <+16>: mov w9, #0xd
0xd立即数给w9
0x100c068d8 <+20>: str w9, [sp, #0x4]
0xd立即数 写入栈空间(0x16b5f3984---0x16b5f3980)
0x100c068dc <+24>: str x8, [sp, #0x8]
x8的地址0x16b5f3984(立即数的地址)存入到栈空间中0x16b5f3988-0x16b5f3990
0x100c068e0 <+28>: adrp x0, 1
0x100c068e4 <+32>: add x0, x0, #0xf2c
(内存的读写往高地址走)
C的数组(指针的基本运算)
int arr[5] = {1,2,3,4,5};
for (int i = 0; i < 5; i++) {
//正常打印
printf("%d",arr[i]);
}
//arr这个变量指向的就是元素的首地址,相当于指针。
int arr[5] = {1,2,3,4,5};
for (int i = 0; i < 5; i++) {
//指针加一相当于指针偏移int个字节。(arr + 1)是地址
//取出地址所指向的数据* (arr + 1)
printf("%d",*(arr + i));
}
举一反三
int * a =arr;
for (int i = 0; i < 5; i++) {
printf("%d",a++);
}
//指针的运算
char ** p1;
//p1所指向的数据类型是char* 的指针,(p1 + 2)偏移16个地址(0x10)
//char * 所指向的数据类型是char , *(xxx + 2)偏移两个地址(0x2)
char c = *(*(p1 + 2) + 2
//和上一句代码的汇编一样。
char c1 = p1[2][2];
0x1042c68f0 <+0>: sub sp, sp, #0x10 ; =0x10
0x1042c68f4 <+4>: ldr x8, [sp, #0x8]
-> 0x1042c68f8 <+8>: ldr x8, [x8, #0x10]
0x1042c68fc <+12>: ldrb w9, [x8, #0x2]
0x1042c6900 <+16>: strb w9, [sp, #0x7]
0x1042c6904 <+20>: add sp, sp, #0x10 ; =0x10
0x1042c6908 <+24>: ret
指针的基本用法
//下面四句代码,两两的汇编代码是一样的(c&c1;d&d1)如图2
char c = *p1;
char c1 = p1[0];
char d = *(p1 + 1);
char d1 = p1[1];
二级指针的反汇编
//多级指针
char ** p1;
char c = **p1;
0x10065e8f0 <+0>: sub sp, sp, #0x10 ; =0x10
-> 0x10065e8f4 <+4>: ldr x8, [sp, #0x8]
0x10065e8f8 <+8>: ldr x8, [x8]
0x10065e8fc <+12>: ldrb w9, [x8]
0x10065e900 <+16>: strb w9, [sp, #0x7]
0x10065e904 <+20>: add sp, sp, #0x10 ; =0x10
0x10065e908 <+24>: ret
参考资料:
--> 一级指针二级指针详解