czytam sobie teraz o obsłudze plików i taki oto przykład z książki "Programowanie w C" autorstwa pana Praty (ma za zadanie dopisać zawartość pliku pierwszego do końca drugiego). Wszystko działa i w ogóle, ale mam problem ze zrozumieniem tego, co się dzieje w tym programie (moje pytania dodałem w komentarzach). Bardzo bym był wdzięczny za rozjaśnienie wątpliwości

 /* dopisz.c -- dopisuje pliki do pliku */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROZMIAR_BUF 1024
#define DLAN 50
char temp[ROZMIAR_BUF];
void dopisz(FILE *zrodlo, FILE *cel);
int main(void)
{
    FILE *pd, *pz;
    int pliki = 0;
    char plik_doc[DLAN];
    char plik_zro[DLAN];
    puts("Podaj nazwe pliku docelowego:");
    gets(plik_doc);
    if ((pd = fopen(plik_doc, "a")) == NULL)
    {
        fprintf(stderr, "Blad otwarcia %s\n", plik_doc);
// fprintf dla stdout by wyświetliło komunikat o błędzie - ale stderr jest to wyjście błędów - co to oznacza konkretnie?
// czy informacje o błędach są gdzieś zapisywane?
        exit(2); 
// co oznaczają exit(1), exit(2), itd? exit(0) kończy program, ale co robi reszta exitów to nie wiem.
    }
    if (setvbuf(pd, NULL, _IOFBF, ROZMIAR_BUF) != 0)
// jak rozumiem pd wskazuje na początek adresu plik_doc, NULL, że bufor jest tworzony automatycznie, _IOFBF - pełne buforowanie
// i cóż oznacza pełne buforowanie? i czym się ono różni od wierszowego (_I0LBF) lub braku buforwania (_I0NBF)
// oraz w jaki sposób zrozumieć buforowanie? tj. tworzymy obszar w pamięci, który przechowa nasze dane z plik_doc? (jak rozumiem
// w tym przypadku o wielkości 1024 bajtów)
    {
        fputs("Nie mozna utworzyc bufora wyjsciowego\n", stderr);
        exit(3);
    }
    puts("Podaj nazwe pierwszego pliku zrodlowego (pusty wiersz konczy program):");
    while (gets(plik_zro) && plik_zro[0] != '\0')
    {
        if (strcmp(plik_zro, plik_doc) == 0)
            fputs("Nie mozna dopisac pliku do siebie\n",stderr);
        else if ((pz = fopen(plik_zro, "r")) == NULL)
            fprintf(stderr, "Blad otwarcia pliku %s\n", plik_zro);
        else
        {
            if (setvbuf(pz, NULL, _IOFBF, ROZMIAR_BUF) != 0)
            {
                fputs("Nie mozna utworzyc bufora wejsciowego\n",stderr);
                continue;
            }
            dopisz(pz, pd);
            if (ferror(pz) != 0)
// jeśli wystąpi błąd to zwróci wartość różną od 0 - ale gdzie sprawdza to, czy wystąpił błąd?
                fprintf(stderr,"Blad odczytu pliku %s\n",
                        plik_zro);
            if (ferror(pd) != 0)
                fprintf(stderr,"Blad zapisu pliku %s\n",
                        plik_doc);
            fclose(pz);
            pliki++;
            printf("Plik %s dopisany.\n", plik_zro);
            puts("Kolejny plik (pusty wiersz konczy program):");
        }
    }
    printf("Koniec. Dopisano %d plikow.\n", pliki);
    fclose(pd);
    return 0;
}
void dopisz(FILE *zrodlo, FILE *cel)
{
    size_t bajty;
// jak rozumiem size_t oznacza typ liczby całkowitej bez znaku - jaki jest sens stosowania go zamiast np unsigned long?
    extern char temp[]; /* korzysta z tablicy zewnetrznej temp */
// tego nie rozumiem, skąd ta zewnętrzna tablica?
    while ((bajty = fread(temp,sizeof(char),ROZMIAR_BUF,zrodlo)) > 0)
// działanie fread też nie do końca rozumiem
        fwrite(temp, sizeof (char), bajty, cel);
}