欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c内存操作感悟(2)

程序员文章站 2022-05-01 10:33:44
...

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

 

如下一段代码正确么(假设文件名为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;
}