In addition to other remarks,
pthread_create(&thr[i], 0, makeRequest, &i);
is incorrect, because i is a local variable, so &i is the same pointer on all your calls to pthread_create
You generally should make the data pointer to your thread routine -here the thread routine is makeRequest either a static pointer, or a unique pointer (unique for each thread); in practice, make it a pointer to some malloc-ed memoory.
A better practice would be declare some struct my_thread_data_st, to uniquely allocate it in the heap with
struct my_thread_data_st* td = malloc(sizeof(struct my_thread_data_st));
if (!td) perror("malloc td"), exit(EXIT_FAILURE);
memset (td, 0, sizeof(struct my_thread_data_st));
// fill td appropriately, then
pthread_create(&thr[i], 0, makeRequest, td);
Or you could have an array of e.g. int-s, e.g. int num[4];, initialize it appropriately, then pthread_create(&thr[i], 0, makeRequest, &num[i]);
Of course, if td is heap-allocated thru malloc, don't forget to free it at the appropriate time, e.g. after the thread ended (e.g. after having pthread_join-ed it). You might be also interested by Boehm's GC and use GC_malloc instead of malloc (then, don't bother about freeing memory, the GC will do it).
If the threads are accessing a shared data, you should serialize access to it with some [global or static] mutex (using pthread_mutex_lock & pthread_mutex_unlock)
Don't forget to call pthread_join on all your threads before exiting -e.g. returning from main.
I suggest reading some pthreads tutorial and some book on advanced linux programming.