C nie dba o ciągi znaków. W rzeczywistości.
Traktuje je jako tablice znaków. Tylko bajty w pamięci. Aby skutecznie z nich korzystać, potrzebne są wskazówki. Nie dlatego, że to zabawa. Ale ponieważ bez nich wykonujesz dodatkową pracę.
Ciąg znaków w C to po prostu „char str[100]”. To wygląda na miejsce na 100 znaków. Ale to nieprawda. Jest to miejsce na 99 znaków plus terminator. C używa ciągów zakończonych zerem. Każda linia kończy się wartością ASCII 0. Zapisana jako '\0'.
To zmienia wszystko.
Inne języki inaczej obsługują ciągi znaków. Pascal używa bajtu długości. Wie dokładnie, ile znaków jest przechowywanych. Zapytaj o długość? Zwróci ten bajt. Natychmiast.
W C musisz liczyć. Odczytuje dane, aż napotka '\0'. To sprawia, że C jest w niektórych przypadkach wolniejszy. W innych szybciej. Wszystko zależy od tego, co robisz.
C nie ma natywnej obsługi ciągów. Opierasz się na bibliotekach. obsługuje wejście i wyjście, funkcje takie jak gets i puts. obsługuje manipulację ciągami. Niektóre systemy używają . Musisz sam zarządzać pamięcią. Nie można po prostu przypisać jednej tablicy do drugiej.
To wszystko. Kopiujesz element po elemencie. Lub użyj strcpy. Główną pracę wykonuje funkcja biblioteczna.
strcpy jest wszędzie w C. Inicjuje ciągi znaków. Kopiuje dane.
Po wykonaniu tego kodu, s1 zawiera „hello”, a s2 także zawiera „hello”. Tablica przechowuje wartości ASCII. Liczby całkowite. h to 104. e to 101. C myśli w bajtach. Myślisz tekstem. Samochodu to nie obchodzi.
Porównanie odbywa się za pomocą strcmp. Zwraca liczbę całkowitą.
Zero oznacza równość. Wartość ujemna oznacza, że pierwszy wiersz jest mniejszy. Wartość dodatnia oznacza, że jest większa.
Istnieją również inne funkcje. strlen zwraca długość. strcat wykonuje konkatenację. Jeśli potrzebujesz więcej informacji, przeczytaj stronę podręcznika.
Ale jak te funkcje działają od wewnątrz? Spójrzmy na „strlen”.
Naiwne podejście wygląda tak:
Większość programistów C nienawidzi tego kodu. Wydaje się to nieskuteczne. Wolą wskazówki.
Można go skompresować jeszcze bardziej.
Prawdziwy ekspert mógłby prawdopodobnie skrócić to jeszcze bardziej.
Skompilowałem te opcje w MicroVAX przy użyciu gcc. Brak optymalizacji. Każdy wariant został wykonany 20 000 razy w 120-znakowej linii.
Pierwsza opcja: 12,3 sekundy.
Opcja druga: 12,3 sekundy.
Trzecia opcja: 12,9 sekundy.
Wskaźniki nie zawsze wygrywają.
Napisz kod, który rozumiesz. Czytelność jest ważniejsza niż kilka mikrosekund. Chyba, że jesteś w ciasnej pętli. Wtedy może warto dokonać optymalizacji.
strcpy przechodzi podobną ewolucję.
Zacznijmy od oczywistości:
Zwróć uwagę na <=. Kopiuje '\0'. Jeśli go pominiesz, linia się nie zakończy. Nieznana długość. Błędy później. Trudno je znaleźć.
Ta wersja jest nieskuteczna. strlen jest wywoływany przy każdej iteracji. Zadzwoń do niej raz.
Teraz wskazówki.
Ściśnij to.
Czysty. Szybko. To niebezpieczne, jeśli nie sprawdzasz swoich granic.
Tak działają ciągi znaków w C. Żadnej magii. Tylko pamięć i wskazówki. I dużo dokładnych obliczeń.
Wskaźniki a wydajność w strcpy
Technicznie rzecz biorąc, możesz napisać while (*s1++ = *s2++);, aby obsłużyć kopiowanie linii. Różnica w wydajności pomiędzy implementacjami naiwnymi a zoptymalizowanymi jest oszałamiająca.
Weź strcpy. W pierwszej wersji skopiowanie 120 znaków 10 000 razy zajmuje 415 sekund. Druga wersja? 14,5 sekundy. Trzeci spada do 9,8 sekundy. Czwarty stabilizuje się na poziomie około 10,3 sekundy.
Nie jest to niewielka różnica. To ogromny wzrost prędkości. Wskaźniki zapewniają tę prędkość, ponieważ eliminują niepotrzebne obciążenie.
Zwraca typy i wskaźniki do ciągów
Prototyp strcpy w bibliotece ciągów ujawnia swój cel:
Większość funkcji łańcuchowych zwraca wskaźnik do łańcucha. strcpy zwraca w rezultacie wartość s1. Pozwala to na wykonanie łańcucha operacji lub natychmiastowe wykorzystanie skopiowanego ciągu bez konieczności dodatkowego wyszukiwania.
Usuń początkowe spacje bez przenoszenia danych
Używanie wskaźników z ciągami znaków często skutkuje pewną poprawą szybkości. Wystarczy trochę pomyśleć, aby to wykorzystać.
Załóżmy, że chcesz usunąć spacje wiodące z ciągu. Instynkt podpowiada Ci przesuwanie znaków, nadpisywanie spacji. W C możesz całkowicie uniknąć ruchu.
Jest to znacznie szybsze niż technika ścinania. Zwłaszcza w przypadku długich linii. Nie przesuwasz bajtów. Po prostu zmieniasz wskaźnik początkowy. Dane pozostają na swoim miejscu. Wniosek się zmienia.
Opanowanie technik
W miarę postępów nauczysz się wielu innych sztuczek ze strunami. Będziesz czytać inny kod. Zobaczysz jak inni pracują z pamięcią.
Praktyka jest kluczem do sukcesu. Nie ma skrótu do odczytania kodu. Trzeba po prostu zobaczyć, jak to się robi i zrozumieć, dlaczego to działa. Wzrost produktywności jest realny. Krzywa uczenia się jest stroma. Ale wyniki mówią same za siebie.



























