Po pierwsze, oto kod:
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
Czy istnieje sposób, aby dowiedzieć się, jaki rozmiar tablicy ptr
wskazuje (zamiast podawać jej rozmiar, czyli cztery bajty w systemie 32-bitowym)?
Odpowiedzi:
Nie możesz. Kompilator nie wie, na co wskazuje wskaźnik. Istnieją sztuczki, takie jak zakończenie tablicy znaną wartością poza pasmem, a następnie zliczanie rozmiaru aż do tej wartości, ale to nie jest używane
sizeof()
.Kolejną sztuczką jest ta wspomniana przez Zana , która polega na tym, żeby gdzieś schować rozmiar. Na przykład, jeśli dynamicznie przydzielasz tablicę, przydziel blok o jeden int większy niż ten, którego potrzebujesz, ukryj rozmiar w pierwszym int i wróć
ptr+1
jako wskaźnik do tablicy. Kiedy potrzebujesz rozmiaru, zmniejsz wskaźnik i zajrzyj do wartości ukrytej. Pamiętaj tylko, aby uwolnić cały blok od początku, a nie tylko tablicę.źródło
Odpowiedź brzmi nie."
Programiści C przechowują gdzieś rozmiar tablicy. Może być częścią struktury lub programista może oszukiwać nieco
malloc()
więcej pamięci niż jest to wymagane w celu przechowywania wartości długości przed rozpoczęciem tablicy.źródło
W przypadku tablic dynamicznych ( malloc lub C ++ nowy ) musisz przechowywać rozmiar tablicy, jak wspomniano przez innych, lub być może zbudować strukturę menedżera tablic, która obsługuje dodawanie, usuwanie, liczenie itp. Niestety C nie robi tego prawie tak dobrze, jak C ++, ponieważ zasadniczo musisz go zbudować dla każdego rodzaju przechowywanego typu tablicy, co jest uciążliwe, jeśli masz wiele typów tablic, którymi musisz zarządzać.
W przypadku tablic statycznych, takich jak ten w twoim przykładzie, do uzyskania rozmiaru używa się wspólnego makra, ale nie jest to zalecane, ponieważ nie sprawdza, czy parametr jest rzeczywiście tablicą statyczną. Makro jest używane w prawdziwym kodzie, np. W nagłówkach jądra Linuksa, chociaż może się nieco różnić od poniższego:
Możesz wyszukiwać w Google z powodów, aby uważać na takie makra. Bądź ostrożny.
Jeśli to możliwe, stdlib C ++, taki jak wektor, jest znacznie bezpieczniejszy i łatwiejszy w użyciu.
źródło
ARRAY_SIZE
makro zawsze działa, jeśli jego argumentem jest tablica (tzn. Wyrażenie typu tablicowego). W przypadku tak zwanej „tablicy dynamicznej” nigdy nie otrzymasz rzeczywistej „tablicy” (wyrażenie typu tablicy). (Oczywiście nie możesz, ponieważ typy tablic uwzględniają ich rozmiar w czasie kompilacji.) Po prostu dostajesz wskaźnik do pierwszego elementu. Twój sprzeciw „nie sprawdza, czy parametr jest rzeczywiście tablicą statyczną”, nie jest tak naprawdę ważny, ponieważ są one różne, ponieważ jedna jest tablicą, a druga nie.Istnieje czyste rozwiązanie z szablonami C ++, bez użycia sizeof () . Następująca funkcja getSize () zwraca rozmiar dowolnej tablicy statycznej:
Oto przykład ze strukturą foo_t :
Wynik:
źródło
T (&)[SIZE]
. Czy możesz wyjaśnić, co to oznacza? Możesz również wspomnieć constexpr w tym kontekście.SIZE
jako argument, to parametr szablonu, który ma być znane z definicji funkcji.)W tym konkretnym przykładzie tak jest, JEŻELI używasz typedefs (patrz poniżej). Oczywiście, jeśli zrobisz to w ten sposób, równie dobrze możesz użyć SIZEOF_DAYS, ponieważ wiesz, na co wskazuje wskaźnik.
Jeśli masz wskaźnik (void *), który jest zwracany przez malloc () lub tym podobne, to nie, nie ma sposobu na określenie struktury danych, na którą wskazuje wskaźnik, a zatem nie ma sposobu na określenie jego rozmiaru.
Wynik:
źródło
Jak podają wszystkie poprawne odpowiedzi, nie można uzyskać tej informacji z samej zepsutej wartości wskaźnika tablicy. Jeśli zanikający wskaźnik jest argumentem odebranym przez funkcję, to rozmiar tablicy inicjującej musi być podany w inny sposób, aby funkcja mogła poznać ten rozmiar.
Oto sugestia inna niż dotychczas, która zadziała: zamiast tego przekaż wskaźnik do tablicy. Ta sugestia jest podobna do sugestii w stylu C ++, z tym wyjątkiem, że C nie obsługuje szablonów ani referencji:
Ale ta sugestia jest trochę głupia dla twojego problemu, ponieważ funkcja jest zdefiniowana tak, aby dokładnie znać rozmiar przekazywanej tablicy (stąd nie ma potrzeby używania sizeof w ogóle na tablicy). Jednak zapewnia pewne bezpieczeństwo. Pozwoli ci to na przejście w szeregu niechcianych rozmiarów.
Jeśli funkcja ma być zdolna do działania na dowolnym rozmiarze tablicy, musisz podać jej rozmiar jako dodatkową informację.
źródło
Nie ma magicznego rozwiązania. C nie jest językiem refleksyjnym. Obiekty nie wiedzą automatycznie, jakie są.
Ale masz wiele możliwości:
źródło
Moim rozwiązaniem tego problemu jest zapisanie długości tablicy w tablicy Array jako meta-informacji o tablicy.
Ale musisz zadbać o ustawienie odpowiedniej długości tablicy, którą chcesz przechowywać, ponieważ nie ma możliwości sprawdzenia tej długości, jak masowo wyjaśnili nasi przyjaciele.
źródło
Możesz zrobić coś takiego:
źródło
Nie, nie można użyć
sizeof(ptr)
do znalezienia rozmiaru tablicy, na którąptr
wskazuje.Chociaż przydzielenie dodatkowej pamięci (większej niż rozmiar tablicy) będzie pomocne, jeśli chcesz przechowywać długość w dodatkowej przestrzeni.
źródło
Rozmiar dni [] wynosi 20, co nie jest liczbą elementów * rozmiar typu danych. Podczas gdy rozmiar wskaźnika wynosi 4 bez względu na to, na co wskazuje. Ponieważ wskaźnik wskazuje na inny element, przechowując jego adres.
źródło
array_size przekazuje do zmiennej size :
Zastosowanie to:
źródło
W łańcuchach
'\0'
na końcu znajduje się znak, więc długość łańcucha można uzyskać za pomocą funkcji takich jakstrlen
. Na przykład problem z tablicą liczb całkowitych polega na tym, że nie można użyć żadnej wartości jako wartości końcowej, więc jednym z możliwych rozwiązań jest zaadresowanie tablicy i użycie jako wartości końcowejNULL
wskaźnika.źródło
NULL
jest prawdopodobnie najmniej wydajną alternatywą, jaką można sobie wyobrazić, aby przechowywać osobnosize
bezpośrednio. Zwłaszcza jeśli cały czas korzystasz z tej dodatkowej warstwy pośredniej.