Q:

Why printf is not working with multple threads in c?

In the code below I create 8 threads and each of those prints a string and its id. However, I don't see any printf output in stdout from PrintHello function. One strange thing that is happening is that if run the main using debugger (CLion) printf indeed outputs the intended output. I actually suspect that no code inside  PrintHello function is run, not just printf. What could be causing this?
Also according to this answer printf is thread-safe so it shouldn't be an issue of different threads competing for stdout.
This is the code (it as adapted from these slides):
#include <stdio.h>
#include <stdlib.h>
#include <ntsid.h>
#include <pthread.h>
#include <unistd.h>

#define BAD_EXIT 1
#define NUM_TASKS 8

char * messages[NUM_TASKS];

void * PrintHello(void * taskIdPtr) {
    int taskId;
    sleep(1);
    taskId = *((int *) taskIdPtr);
    printf("Task id = %d, message = %s\n", taskId, messages[taskId]);
    free(taskIdPtr);
    pthread_exit(NULL);
}
int main(int argc, char ** argv) {
    pthread_t threads[NUM_TASKS];
    int * taskIdPtr;
    int rc, t;
    messages[0] = "English: Hello World!";
    messages[1] = "French: Bonjour, le monde!";
    messages[2] = "Spanish: Hola al mundo";
    messages[3] = "Klingon: Nuq neH!";
    messages[4] = "German: Guten Tag, Welt!";
    messages[5] = "Russian: Zdravstvytye, mir!";
    messages[6] = "Japan: Sekai e konnichiwa!";
    messages[7] = "Latin: Orbis, te saluto!";

    for(t = 0; t < NUM_TASKS; t++) {
        taskIdPtr = (int *) malloc(sizeof(int));
        *taskIdPtr = t;
        printf("Creating thread %d\n", t);
        rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskIdPtr);
        if(rc) {
            perror("Error :");
            exit(BAD_EXIT);
        }
    }
    return 0;
}

A:

The problem is that your main thread completes its execution and exits before any other child thread even prints a single message(Since in your child thread you are waiting for 1 second before doing anything).
As soon as the main thread exits, all other child threads also exits and you don't see any message on your screen. 
Following is an extract of linux manual page of pthread_create():

The new thread terminates in one of the following ways:

It calls pthread_exit(3), specifying an exit status value that is available to another thread in the same process that calls pthread_join(3).
It returns from start_routine().  This is equivalent to calling pthread_exit(3) with the value supplied in the return statement.
It is canceled (see pthread_cancel(3)).
Any of the threads in the process calls exit(3), or the main thread performs a return from main().  This causes the termination of all threads in the process.

To solve this problem you should use int pthread_join(pthread_t thread, void **retval).
Following is corrected code. See it working here:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#define BAD_EXIT 1
#define NUM_TASKS 8

char * messages[NUM_TASKS];

void * PrintHello(void * taskIdPtr) {
    int taskId;
    sleep(1);
    taskId = *((int *) taskIdPtr);
    printf("Task id = %d, message = %s\n", taskId, messages[taskId]);
    free(taskIdPtr);
    pthread_exit(NULL);
}
int main(int argc, char ** argv) {
    pthread_t threads[NUM_TASKS];
    int * taskIdPtr;
    int rc, t;
    messages[0] = "English: Hello World!";
    messages[1] = "French: Bonjour, le monde!";
    messages[2] = "Spanish: Hola al mundo";
    messages[3] = "Klingon: Nuq neH!";
    messages[4] = "German: Guten Tag, Welt!";
    messages[5] = "Russian: Zdravstvytye, mir!";
    messages[6] = "Japan: Sekai e konnichiwa!";
    messages[7] = "Latin: Orbis, te saluto!";

    for(t = 0; t < NUM_TASKS; t++) {
        taskIdPtr = (int *) malloc(sizeof(int));
        *taskIdPtr = t;
        printf("Creating thread %d\n", t);
        rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskIdPtr);
        if(rc) {
            perror("Error :");
            exit(BAD_EXIT);
        }
    }

    for(t = 0; t < NUM_TASKS; t++)
    {
        pthread_join(threads[t], NULL);
    }
    return 0;
}

A:

The main process is exiting before the newly created threads gets executed. So you should wait for the threads created using pthread_join.
As per the man page of pthread_join
int pthread_join(pthread_t thread, void **retval);
The  pthread_join()  function waits for the thread specified by thread to terminate.  If that thread has already terminated, then pthread_join() returns immediately.  The thread specified by thread must be joinable.

