2013-02-21 6 views
15

Jak wskazuje tytuł, moje pytanie brzmi: jak uzyskać rozmiar ciągu znaków w C. Czy warto używać sizeof, jeśli zadeklarowałem (ciąg) w funkcji bez malloc w nim? Lub, jeśli zadeklarowałem to jako wskaźnik? Co się stanie, jeśli zainicjuję go za pomocą malloc? Chciałbym uzyskać wyczerpującą odpowiedź.Jak uzyskać rozmiar ciągu w bajtach?

+1

Z twojego pytania nie wynika jednoznacznie, czy chcesz znać rozmiar "łańcucha", czy rozmiar tablicy znaków/bloku pamięci zawierającego "ciąg". – alk

+0

@alk Edytowano. Mam nadzieję, że będę bardziej przejrzysty. Dzięki. – artaxerxe

Odpowiedz

36

Można użyć strlen. Rozmiar jest określany przez kończący znak null, więc przekazany ciąg powinien być poprawny.

Jeśli chcesz uzyskać rozmiar bufora pamięci, który zawiera kryteria, a masz wskaźnik do niego:

  • Jeśli jest dynamiczny array (stworzony z malloc), to jest niemożliwe, aby dostać go rozmiar, ponieważ kompilator nie wie, na co wskazuje wskaźnik. (check this)
  • Jeśli jest to tablica statyczna, można użyć numeru sizeof, aby uzyskać jego rozmiar.

Jeśli nie masz pewności co do różnicy między tablicami dynamicznymi i statycznymi, sprawdź numer this.

+12

Właściwie rozmiar to 'strlen() + 1' (1 dla znaku kończącego) –

+6

@ 0x69 Rozmiar ciągu * * jest zwykle definiowany jako wykluczający terminator kończący. – Dukeling

+0

czy typ "char" w "c" ma zawsze rozmiar bajtu? – artaxerxe

10

Użyj strlen, aby uzyskać długość zakończonego znakiem łańcucha znaków.

sizeof zwraca długość szeregu nie będącego łańcuchem. Jeśli jest to wskaźnik (char *s), a nie tablica (char s[]), nie będzie działać, ponieważ zwróci rozmiar wskaźnika (zwykle 4 bajty w systemach 32-bitowych). Wierzę, że tablica zostanie przekazana lub zwrócona jako wskaźnik, więc stracisz możliwość używania sizeof, aby sprawdzić rozmiar tablicy.

Więc tylko jeśli ciąg obejmuje cały wachlarz (np char s[] = "stuff"), by za pomocą sizeof dla statycznie zdefiniowane return array, co chcesz (i być szybciej, ponieważ nie musiałaby pętli znaleźć null-terminator) (jeśli ostatni znak jest terminatorem o wartości NULL, musisz odjąć 1). Jeśli nie obejmuje całej tablicy, nie zwróci tego, co chcesz.

Alternatywą dla tego wszystkiego jest przechowywanie w rzeczywistości rozmiaru napisu.

+2

Należy zauważyć, że 'sizeof' w rzeczywistości nie podaje długości ciągu znaków. W przypadku literału łańcuchowego 'sizeof' zawiera terminator o wartości null. Dla tablicy 'char',' sizeof' podaje liczbę elementów w tablicy (która jest nieprzewidywalną wielkością większą niż długość łańcucha zawartości tablicy) – simonc

+1

Może być sens, aby wskazać, że 'strlen' i' sizeof' zwracają dwie podstawowe różne rzeczy. – alk

+0

@ simon Edytowane. – Dukeling

10

Podczas sizeof prace dla tego szczególnego rodzaju wyrażenie:

char str[] = "content"; 
int charcount = sizeof str - 1; // -1 to exclude terminating '\0' 

to nie zadziała, jeżeli str jest wskaźnik (powraca sizeof wielkość wskaźnika, zazwyczaj 4 lub 8) lub tablicę o określonej długości (sizeof zwróci liczba bajtów pasująca do podanej długości, która dla typu znaku jest taka sama).

Po prostu użyj strlen().

+0

w twoim przykładzie, ponieważ str jest nazwą typu, czy nie powinna być nawiasowana? – ramrunner

+0

@ramrunner 'str' jest nazwą zmiennej. Jest to tablica, więc 'sizeof str' zwróci rozmiar całej tablicy w bajtach. Kiedy tablica jest zadeklarowana jak wyżej, rozmiar tablicy jest dokładnie wielkości literału, łącznie z kończeniem ''\ 0''. I 'sizeof' ma wyższy priorytet niż' -', więc 'sizeof str' nie potrzebuje żadnego nawiasu, chociaż dodanie ich dla jasności nie byłoby tutaj złe, przyznaję. – hyde

1

lubię używać:

(strlen(string) + 1) * sizeof(char) 

To daje rozmiar bufora w bajtach. Możesz użyć tego z snprintf() może pomóc:

const char* message = "%s, World!"; 
char* string = (char*)malloc((strlen(message)+1))*sizeof(char)); 
snprintf(string, (strlen(message)+1))*sizeof(char), message, "Hello"); 

Pozdrawiam!Funkcja: size_t strlen (const char *s)

+0

(1) 'strlen()' zawsze zwraca długość w bajtach, mnożenie jej przez 1 nic nie dodaje; (2) Nie może istnieć związek między rozmiarem bufora a długością łańcucha, który zawiera; (3) Czy próbowałeś skompilować którykolwiek z tego kodu? –

+0

(1) Nie mnożyłem przez jeden (2) Przydzielam bajtom wskaźnik, więc używam długości łańcucha * sizeof znaku (inbytes) (3) Używam go cały czas. –

+0

Jeśli chcesz zbudować rep, musisz to zrobić, zapewniając dobre odpowiedzi. Najnowsza edycja przynajmniej usuwa poprzednie błędy, ale teraz to nawet nie jest odpowiedź, to komentarz. Wszystkie inne odpowiedzi odnoszą się do 'strlen()' i dają pewne znaczące wyjaśnienie, to nie jest odpowiednia odpowiedź. –

3

Jeśli używasz sizeof() następnie char *str i char str[] powróci różne odpowiedzi. char str[] zwróci długość ciągu znaków (łącznie z terminatorem ciągu), podczas gdy char *str zwróci rozmiar wskaźnika (różni się w zależności od kompilatora).