不从分配的地址开始访问, 希望跳过一些字节, 怎么处理?
如下一段代码正确么(假设文件名为test.c)?
#include#include int main(void) { void *p = malloc(20); printf("%p\n", p); char *t = (char *)(p + 1); printf("%p\n", t); free(p); return 0; }
使用gcc -S -masm=intel test.c生成intel
格式的汇编
mov DWORD PTR [esp], 20 call _malloc mov DWORD PTR [esp+28], eax mov eax, DWORD PTR [esp+28] mov DWORD PTR [esp+4], eax mov DWORD PTR [esp], OFFSET FLAT:LC0 call _printf mov eax, DWORD PTR [esp+28] add eax, 1 mov DWORD PTR [esp+24], eax mov eax, DWORD PTR [esp+24] mov DWORD PTR [esp+4], eax mov DWORD PTR [esp], OFFSET FLAT:LC0 call _printf mov eax, DWORD PTR [esp+28] mov DWORD PTR [esp], eax call _free
可以看到(char *)(p + 1), 仅仅是将指针p进行加1运算, 其实, 进一步是考虑, 对指针加N, 指针前进"当前指针指向的数据类型的长度*N", 但是void *, 是不知道具体的数据类型是怎样的, gcc这里是将这种情况当做char类型来处理了, 所以地址直接加1, 编译也能通过.
但是同样的代码, 在vc中是通不过编译的, char *t = (char *)(p + 1);这一行和预期的一样, 报错如下:
error C2036: “void *”: 未知的大小
如果要都能通过编译, 其实可以两种做法:
方法一, 其实一个指针可以强制转换为整数的, 就是这个指针的地址值, 对这个值可以做加减, 之后整数也是可以强制转换为指针的, 当做地址使用.
#include#include int main(void) { void *p = malloc(20); printf("%p\n", p); long pt = (long)p; char *t = (char *)(pt + 1); printf("%p\n", t); free(p); return 0; }
方法二, 常规方法, 先得到地址, 指针加+1.
#include#include int main(void) { void *p = malloc(20); long pt = (long)p; char *t = (char *)(p); t++; printf("%p\n", p); printf("%p\n", t); free(p); return 0; }