programowanieProgramista C

Jak realizowana jest praca z łańcuchami w C? Wyjaśnij różnicę między tablicą znaków a wskaźnikiem na łańcuch. Jak unikać błędów podczas pracy z łańcuchami?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W języku C łańcuchy są realizowane jako tablice znaków, kończące się bajtem zerowym ('\0'). Przykład deklaracji łańcucha:

char str1[] = "hello"; // Tablica z 6 znakami: {'h','e','l','l','o','\0'} char *str2 = "hello"; // Wskaźnik na literał łańcuchowy
  • Tablica znaków: Przydziela pamięć dla każdego elementu, w tym dla kończącego zera. Tablicę można modyfikować (jeśli nie jest const).
  • Wskaźnik na łańcuch: Może wskazywać na literał łańcuchowy (którego nie można modyfikować), lub na przydzielony obszar pamięci. Literał łańcuchowy zazwyczaj znajduje się w segmencie tylko do odczytu.

Aby unikać błędów:

  • Prawidłowo zarządzaj pamięcią (używaj malloc, strcpy, sprawdzaj rozmiar bufora).
  • Nie używaj literałów łańcuchowych do modyfikacji.
  • Sprawdzaj, czy wszystkie łańcuchy kończą się \0.

Przykład poprawnej pracy z łańcuchem:

char buffer[100]; strcpy(buffer, "test"); // OK, buffer jest zmienny i gwarantuje zawartość '\0'

Pytanie z pułapką

Jaki będzie wynik wykonania następującego kodu i do jakich błędów doprowadzi?

char *str = "hello"; str[0] = 'H'; printf("%s ", str);

Odpowiedź: Program doprowadzi do nieokreślonego zachowania, prawdopodobnie — błędu segmentacji, ponieważ literały łańcuchowe umieszczane są w obszarze pamięci tylko do odczytu. Nie wolno przypisywać wartości pod adresem literału łańcuchowego.

Przykłady rzeczywistych błędów z powodu nieznajomości subtelności tematu


Historia Zespół pomylił pojęcia tablica łańcucha i wskaźnik na literał. Jedna funkcja przyjęła char *output = "default"; i następnie wykonała strcpy(output, input);, co prowadziło do awarii podczas pierwszego uruchomienia, ponieważ kopiowanie następowało w pamięci tylko do odczytu.


Historia Podczas pracy z siecią wynik działania był zapisywany w buforze, przydzielonym za pomocą char *buf = NULL; strcpy(buf, data);. Doprowadziło to do zapisu w nieinicjalizowanej pamięci i awarii aplikacji.


Historia W pakiecie lokalizacyjnym zespół przekazywał łańcuchy między komponentami, nie upewniwszy się, że dodano znak \0. Pewnego razu funkcja wydrukowała śmieci w konsoli i uszkodziła wewnętrzną strukturę pamięci.