Split a string and write the i-th element into a buffer with C
Before we talk about improving the efficiency of your function, lets talk about safety:

You never check the validity of your function parameters.
You have no way of knowing how big buff is.

For the first issue, if str or delim is null, passing them directly in to strstr will cause a segfault and crash your program.
The second issue is worse: if buff is smaller then str, your function may end up clobbering memory when it tries to copy from str to buff.
This is undefined behavior, and the results are unpredictable.
Now for some efficiency suggestions:

Calculate string length only once.
Since strlen works by running over the string looking for '\0' terminator, it is more efficient to call it only once at the beginning of your function and store the result in a variable.
This can also allow you to implement a simple shortcut for edge cases such as where str or delimiter are empty strings, or delimiter is longer then str.

You don't need your own while loop at the end and the buff_i variable.
You can simply use memcpy or strncpy to copy the element in to the buffer.
memcpy would be slightly more efficient, since it does not check for '\0', while strncpy does.

Since your logic is that if delimiter is never found, but the requested element is 0 the result is &quot;success&quot;, you don't need to handle this as a separate edge case.
That means you can get rid of the first if block, and handle everything in one loop.
You can also get rid of the special checks in the if loop and just focus on the search.


The following code example does not include the suggested validity checks:
int i;
char *start = str;
char *end = start;
size_t delim_len = strlen(delim);
size_t copy_len;

for (i = 0; i &lt;= index &amp;&amp; end != NULL; i++) {
    end = strstr(start, delim);
    if (end != NULL &amp;&amp; i != index) start = end + delim_len;
}

/* element not found */
if (i != index) return index;

if (end == NULL) {
    copy_len = strlen(start);
} else {
    copy_len = (ssize_t)(end - start);
}

memcpy(buff, start, copy_len);
buff[copy_len] = '\0';

return 0;