В Windows вы можете конвертировать из ANSI в UTF16, а затем конвертировать из UTF16 в UTF8.
Вы не можете конвертировать между наборами символов по 1 байту за раз.Весь файл должен быть прочитан в буфер и преобразован.Обратите внимание, что каждая кодовая точка Unicode составляет от 1 до 4 байтов в UTF8, в то время как она составляет 2 или 4 байта в UTF16 и всегда 1 байт в ANSI.
int main(void)
{
FILE* src = fopen("source.txt", "rb");
if(!src) return 0;
FILE* dst = fopen("destination.txt", "wb");
if(!dst) return 0;
fseek(src, 0, SEEK_END);
long filesize = ftell(src);
char *ansi = malloc(filesize);
fseek(src, 0, SEEK_SET);
fread(ansi, 1, filesize, src);
int codepage = CP_ACP;
int u16size = MultiByteToWideChar(codepage, 0, ansi, filesize, NULL, 0);
wchar_t *u16 = malloc(u16size * sizeof(wchar_t));
MultiByteToWideChar(codepage, 0, ansi, filesize, u16, u16size);
int u8size = WideCharToMultiByte(CP_UTF8, 0, u16, u16size, NULL, 0, NULL, FALSE);
char *u8 = malloc(u8size);
WideCharToMultiByte(CP_UTF8, 0, u16, u16size, u8, u8size, NULL, FALSE);
fwrite(u8, 1, u8size, dst);
return 0;
}