【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

void*とオフセット

第6回 コンパイラ実装会で出た話題です。

以下のコードがエラーになります。なぜ?

test.cpp
#include <stdlib.h>

int main(void) {
    void *p = malloc(100);
    *(void **)&p[10] = reinterpret_cast<void *>(free);
    return 0;
}
コンパイル結果
$ g++ test.cpp
test.cpp: In function 'int main()':
test.cpp:5:20: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
test.cpp:5:20: error: 'void*' is not a pointer-to-object type

voidは実体がないのでvoid*はdereferenceできません。void型の変数がエラーになるのと同じ理屈です。

test.cpp
int main(void) {
    void a;
    return 0;
}
コンパイル結果
$ g++ test.cpp
test.cpp: In function 'int main()':
test.cpp:4:10: error: variable or field 'a' declared void

バイト単位で位置を取りたいなら、char*にキャストすればうまくいきます。

#include <stdlib.h>

int main(void) {
    char *p = reinterpret_cast<char *>(malloc(100));
    *(void **)&p[10] = reinterpret_cast<void *>(free);
    return 0;
}

なぜnewを使わずにmalloc()なのか?と思われるかもしれません。実際はmmap()を使っていましたが、例として単純化するためmalloc()に置き換えて説明しました。