String joining function in C
I see a number of things that may help you improve your code.

Use standard library functions where appropriate

Except as a learning exercise (which I recognize this probably is), there's little reason to write duplicates of existing, well-tested, well-documented and often highly optimized library functions.  For that reason, in real code, I'd expect strlen() to be used rather than myStrLen().

Don't leak memory

Unlike Java, in C it is the responsibility of the programmer to clean up memory allocations.  For that reason, I'd expect the sample code to have the line free(joined); before the end of main.

Use const where appropriate

The delimiter and strArr arguments to awfulJoinStr are not and should not be modified by that function, so it would be better to indicate that fact and change the parameter list to this:

char* awfulJoinStr(const char* delimiter, const char** strArr, size_t nStrings)


Consider using a sentinel value

Generally, there are two ways to tell a function the size of a list.  Either it can be passed explicitly as you do in the current code, or one can use a sentinel value which is simply a special "end of list" marker value.  In this case, I think it might be more convenient to use a sentinel value of NULL.  So your coll could look like this:

const char* coll[] = {"Hello", "World", "This", "Should", "Be", "Joined!", NULL};


And now the code could look for the special NULL value instead of having to pass a count.

Check for errors

The call to malloc could fail.  The only indication you would have of this would be that it would return NULL, so for that reason, you should check for a NULL return from malloc before using the returned pointer or risk having your code crash.

Also, if nStrings is zero, the calculated totalDelimiterSize is huge and the result will certainly not be what you want, even if it doesn't crash.

Simplify code by knowing the standard well

The current code includes this line:

char* buffer = malloc(sizeof(char) * bufferSize);


However, the standard defines sizeof(char) as always being equal to 1 so this could and should be written like this instead:

char* buffer = malloc(bufferSize);


Bail out early on error

If the parameters to the function are faulty, or if there are no passed strings, it would probably make most sense to bail out early, rather than doing a bunch of work that would ultimately be thrown away.  

Understand the use of pointers

A fundamental (but not always easy!) concept in C programming is the pointer.  Understanding how to use pointers effectively is an important skill to learn when mastering C programming.  Examples as applied to this program are shown in the code in the next section.

Simplify your code by decomposing into functions

Here's one way to rewrite the function using most of what's suggested above:

char* awfulJoinStr(const char* delimiter, const char** strArr) {
    if (strArr == NULL || delimiter == NULL) {
        return NULL;
    }
    // first calculate the total length of the strings
    size_t bufferSize = 0;
    size_t nStrings = 0;
    for (const char **str = strArr; *str != NULL; ++str) {
        bufferSize += strlen(*str);
        ++nStrings;
    }
    if (nStrings == 0) {
        return NULL;
    }
    size_t delimiterSize = strlen(delimiter);
    bufferSize += (nStrings - 1) * delimiterSize + 1;
    char* buffer = malloc(bufferSize);
    if (buffer == NULL) {
        return NULL;
    }
    buffer[bufferSize - 1] = '\0';
    for (char *curr = scopy(buffer, *strArr++); *strArr; ++strArr) {
        curr = scopy(curr, delimiter);
        curr = scopy(curr, *strArr);
    }
    return buffer;
}


As you see, the copying is done via a custom string copy function scopy.  We use this instead ofthe standard strcpy because strcpy returns the start of the destination string, but this code requires one past the end instead.  Here's scopy:

char *scopy(char *dest, const char *src) {
    while (*src) {
        *dest++ = *src++;
    }
    return dest;
}


This short function uses a lot of specialized C knowledge.  First, the passed parameters are both pointers.  We can alter the pointers without necesarily altering what they're pointing to.  Second is the idea of post-increment versus pre-increment.  This line is a very common C idiom:

*dest++ = *src++;


What it means in English is, in effect, "get the thing that src is pointing to and copy that to wherever dest is pointing; then increment both pointers."  (That's not exactly the sequence of events, but it will suffice to understand the intent of this line.)