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

 

 

發佈了151 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章