Wydaje się to mato skomplikowane, prawda? Jednakże sprawdźmy opis funkcji strncpy w podręczniku Visual C++.
Funkcja strncpy kopiuje n pierwszych znaków strŻródlo do strCel i zwraca wskaźnik strCel. Jeśli liczba n jest mniejsza niż długość strZródło lub równa tej długości, to znaki puste NIE zostają dodane automatycznie do kopiowanego napisu. Jeśli liczba n jest większa niż długość strŹródło, to napis docelowy jest wypełniany brakującymi znakami pustymi.
Oznacza to, że musimy rozpatrzyć dwa przypadki: (I) kopiowany napis jest mniejszy niż bufor oraz (2) napis jest tej samej wielkości, co bufor lub od niego większy.
Jeśli napis jest mniejszy, to wszystko jest w porządku. Będzie on zakończony znakiem pustym i zostanie pomyślnie skopiowany do bufora. Jeśli napis jest większy od bufora lub ma tę samą wielkość, to kopiowany napis nie będzie zakończony znakiem pustym. Może to wywołać różne usterki. (Na przykład funkcja strłen wywołana na napisie niezakończonym znakiem pustym może przeszukać po kolei całą pamięć i zatrzymać się dopiero w miejscu, w którym napotka znak pusty.)
Musimy zająć się tym wyjątkowym przypadkiem i na końcu bufora pozostawić miejsce na znak pusty. Dlatego właśnie odejmujemy 2 od rozmiaru bufora. Następnie gwarantujemy, że ostatni znak w buforze jest zawsze zerem.
Przykład: Literał: :&operator= w pliku regexp.h
unikanie awarii; unikanie nieoczekiwanych wyników
Przed
const Literał &operator=(const char *pch)
strncpy(m_rgch, pch, sizeof(m_rgch)-1); return *this;
Po
const Literał &operator=(const char *pch)
strncpy(m_rgch, pch, sizeof(m_rgch)-2); m_rgch[sizeof(m_rgch) - 1] - 0; return *this;