В вашей программе strcat () сначала просматривает str [10] и сканирует вперед в поисках символа конца строки (NUL / ноль). Когда он находит это, он копирует строку в начале test [], пока не достигнет NUL в конце этой строки.
То, что вы хотите, это:
str[10] = [NUL,?,?,?,?,?,?,?,?,?]
test[3] = [a,b,NUL]
но то, что у вас есть на самом деле, это:
str[10] = [?,?,?,?,?,?,?,?,?,?,?,?,?,?,...]
test[2] = [a,b,?,?,?,?,...]
Strcat будет копировать до тех пор, пока не найдет ноль, который может быть за тысячи байтов за концом массива. Вы либо получите ошибку сегмента, либо перезапишите случайные данные. Strcat ничего не знает о ваших размерах массива.
Строка "ab" требует массива длины [3], потому что она также содержит символ NUL, поэтому ваше объявление для теста слишком мало.
В C строка в кавычках автоматически включает NUL в конце, а массив - нет. То, что вы хотите, выглядит примерно так:
char str[10] = {'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
char test[3] = {'a','b','\0'};
Или вы можете написать это более просто так:
char str[10] = "";
char test[3] = "ab";