`
jimmee
  • 浏览: 530686 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

c内存操作感悟(2)

阅读更多

不从分配的地址开始访问, 希望跳过一些字节, 怎么处理?

 

如下一段代码正确么(假设文件名为test.c)?

 

#include <stdio.h>
#include <stdlib.h>

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 <stdio.h>
#include <stdlib.h>

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 <stdio.h>
#include <stdlib.h>

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;
}

 

 

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics