不從分配的地址開始訪問, 希望跳過一些字節, 怎麼處理?
如下一段代碼正確麼(假設文件名爲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; }