汎用ポインタを使う

int型のポインタとchar型のポインタは違う型のため、同じものとして扱うことは出来ません。
ですが、実際にはポインタ型はメモリ上の特定アドレスを示すもののため、
どの型のポインタであっても、データ自体はメモリ上のアドレスを示す何bitかの数値であり、全く同じです。
(勿論、ポインタの示すアドレスに何があるかは異なります)

そのため、ポインタ専用の変数を利用することで、あらゆる型のポインタを同じ変数に代入することができます。

ただし、コンパイラの型チェックが効かなくなる等の理由から、基本的にはオススメできない手法です。
C++の場合はテンプレートやクラスの継承、dynamic_castで解決できる場合はそちらを利用した方が安全です。

汎用ポインタ

void *型は汎用ポインタと呼ばれ、あらゆるポインタを代入することができます。
これはたとえば以下のように、何の型かは指定しないけど、変数として持ちたいという場合に利用できます。

この場合、変数定義をvoid *型にしておき、使う前後に目的の型にキャストすることで、
様々な型を1つの変数で扱うことが出来ます。

struct Container{
  void* data;
};

struct Num{
  int n;
};

const char* text = "text";
Container con1;
con1.data = (void*)text; // dataにconst charのポインタを入れる

Num* numPointer = new Num();
numPointer->n = 42;
Container con2;
con2.data = (void*)numPointer; // dataにNum型のポインタを入れる

printf("%s\n", (const char*)con1.data); // 取り出す際にキャストする
printf("%d\n", ((Num*)con2.data)->n);

なお、違うポインタを違う型にキャストして使うと、メモリ破壊などの予期せぬエラーを引き起こしますが、
構文上はvoid *から元の型に戻す際のキャストは全て正しいと処理されます。

そのため、おかしくなるキャストをしていてもコンパイラの型チェックでエラー検出が出来ません。
前述の通り、C++の場合はvoid *を使わず、テンプレートやクラスの継承、dynamic_castで解決した方が安全です。

mallocの戻り値

void *はmallocの戻り値としても使われています。
http://www.cplusplus.com/reference/cstdlib/malloc/

mallocの戻り値が何にでもキャスト出来るのは、この仕様によるものです。 

ポインタを整数値として扱う

ポインタを整数値として利用したい場合、intptr_tとuintptr_tが利用できます。
これはそれぞれ符号つき、符号なしの整数として扱うことができます。

間違ってもそのままintにキャスとして代入してはいけません。
void型のポインタとint型を相互変換するなという話