W kursie wprowadzającym do języka C nauczyłem się, że podczas przechowywania łańcuchy są przechowywane \0
na końcu ze znakiem zerowym . Ale co, jeśli chciałbym wydrukować ciąg, powiedz, printf("hello")
chociaż zauważyłem, że nie kończy się \0
na poniższym stwierdzeniu
printf("%d", printf("hello"));
Output: 5
ale wydaje się to niespójne, o ile wiem, że zmienne, takie jak łańcuchy, są przechowywane w pamięci głównej i wydaje mi się, że podczas drukowania coś może być również przechowywane w pamięci głównej, to dlaczego różnica?
);
, co zamierzasz pokazać za pomocą tego kodu? Jak udowodniłeś, że to nie kończy się na\0
?Odpowiedzi:
Bajt zerowy oznacza koniec łańcucha. Nie jest liczony do długości łańcucha i nie jest drukowany, gdy łańcuch jest drukowany
printf
. Zasadniczo bajt zerowy mówi funkcjom, które wykonują manipulacje ciągami, kiedy zatrzymać.Różnica polega na tym, że utworzysz
char
tablicę zainicjowaną łańcuchem. Użyciesizeof
operatora odzwierciedla rozmiar tablicy, w tym bajt zerowy. Na przykład:źródło
printf()
. TBH Nie mam pojęcia, jak toprintf()
działa.printf
zwraca liczbę wydrukowanych znaków.'\0'
nie jest drukowany - oznacza to tylko, że w tym ciągu nie ma już znaków. Nie jest również liczony do długości łańcuchahttps://godbolt.org/z/wYn33e
źródło
Twoje założenie jest błędne. Twój ciąg rzeczywiście kończy się na
\0
.Zawiera 5 znaków
h
,e
,l
,l
,o
i 0 charakterze.Wyjściowe
print()
wywołanie „wewnętrzne” to liczba wydrukowanych znaków, a to 5.źródło
W C wszystkie ciągi literalne są tak naprawdę tablicami znaków, które zawierają null-terminator.
Jednak terminator zerowy nie jest liczony jako długość łańcucha (dosłownie lub nie) i nie jest drukowany. Drukowanie zatrzymuje się po znalezieniu terminatora zerowego.
źródło
printf
byłoby zerowego terminatora, to wykraczałby poza granice łańcucha i drukowałby „losowe” lub „śmieciowe” znaki i zwracał liczba różna od długości ciągu. Jeśli znasz już długość łańcucha, możesz również sprawdzić, czy znak pod tym indeksem jest'\0'
, co będzie działać, ale będzie technicznie niezdefiniowanym zachowaniem, jeśli rozmiar tablicy nie zawiera terminatora (jak wchar arr[5] = "hello";
, który nie doda terminator do tablicy).char * p = "Hello"; int i = 0; while (p[i] != '\0') { printf("%d: %c", i, p[i]); i++; }
i zobaczyć, jak to działa: pokazuje linie z indeksami i zawartość w tym wierszu. Po indeksie 4 znajduje znak 0 i przerywa pętlę while. Tam widzisz, że jest 0 znaków.Wszystkie odpowiedzi są naprawdę dobre, ale chciałbym dodać kolejny przykład, aby je wszystkie uzupełnić
Dla tych, którzy nie chcą wypróbować tego na gdb online, wynik jest następujący:
https://linux.die.net/man/3/printf
Czy to pomaga zrozumieć, co robi terminator ucieczki? Nie jest to granica dla tablicy znaków ani łańcucha. To postać, która powie facetowi, który analizuje -STOP, (drukuj) parsuj aż do tego momentu.
PS: A jeśli parsujesz i wydrukujesz go jako tablicę znaków
dostajesz:
gdzie, spacja po podwójnym l, jest zakończeniem zerowym, jednak parsowanie tablicy char spowoduje tylko wartość char każdego bajtu. Jeśli wykonasz inną analizę i wydrukujesz wartość int każdego bajtu („% d%, char_array [i]), zobaczysz, że (otrzymasz reprezentację kodu ASCII-int) biała spacja ma wartość 0.
źródło
W
C
funkcjiprintf()
zwraca liczbę znaków drukowanego,\0
jest tonull
terminator, który jest używany do wskazania końca ciągu znaków w języku C i tam nie jest zbudowany wstring
rodzaju jak zc++
jednak twoje potrzeby rozmiar tablicy być przynajmniej większa niż liczbachar
ciebie chce przechować.Oto ref: cpp ref printf ()
źródło
Mylisz się. To stwierdzenie nie potwierdza, że literał łańcucha
"hello"
nie kończy się znakiem kończącym zero'\0'
. To stwierdzenie potwierdziło, że funkcjaprintf
wyprowadza elementy łańcucha, dopóki nie zostanie napotkany znak kończący zero.Gdy używasz literału ciągowego, jak w powyższej instrukcji, kompilator tworzy tablicę znaków o statycznym czasie przechowywania, który zawiera elementy literału ciągowego.
W rzeczywistości to wyrażenie
jest przetwarzany przez kompilator w sposób podobny do następującego
Działanie funkcji printf w tym można sobie wyobrazić w następujący sposób
Aby uzyskać liczbę znaków zapisanych w ciągu literowym „hello”, możesz uruchomić następujący program
Wyjście programu to
źródło
Najpierw musisz wyczyścić swoją koncepcję. Ponieważ zostanie ona wyczyszczona, gdy zajmujesz się tablicą, użyte polecenie drukowania po prostu zlicza znaki umieszczone w nawiasie. Jest niezbędny w ciągu tablicowym, aby kończył się na \ 0
źródło
Łańcuch jest wektorem znaków. Zawiera sekwencję znaków tworzących ciąg, a następnie ciąg znaków specjalnych na końcu: „\ 0”
Przykład: char str [10] = {'H', 'e', 'l', 'l', 'o', '\ 0'};
Przykład: następujący wektor znaków nie jest jednym ciągiem, ponieważ nie kończy się na „\ 0”
char str [2] = {'h', 'e'};
źródło