Pliki nagłówkowe stdlib.h i stddef.h definiują typ danych o nazwie size_t, który jest używany do reprezentowania rozmiaru obiektu. Funkcje biblioteczne, które przyjmują rozmiary, oczekują, że będą one typu size_t, a operator sizeof oblicza rozmiar_t.
Rzeczywisty typ size_t jest zależny od platformy; częstym błędem jest założenie, że size_t jest tym samym, co unsigned int, co może prowadzić do błędów w programowaniu, zwłaszcza gdy coraz bardziej rozpowszechnione są architektury 64-bitowe.
@NDEthos To zależy! W tym miejscu Linux /usr/include/stdlib.hpobiera definicję skąd /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.hi tam jest ona ustawiona domyślnie, long unsigned intchyba że inny plik nagłówkowy mówi inaczej.
size_t to typ używany do reprezentowania rozmiarów (jak sugeruje jego nazwa). Jego platforma (a nawet potencjalnie implementacja) jest zależna i powinien być używany tylko w tym celu. Oczywiście, reprezentując rozmiar, size_t jest bez znaku. Wiele funkcji z biblioteki standardowej, w tym malloc, sizeof i różne funkcje operacji na łańcuchach, używa size_t jako typu danych.
Wartość int jest domyślnie podpisywana i chociaż jego rozmiar jest również zależny od platformy, na większości nowoczesnych maszyn będzie to stały 32-bitowy (i chociaż size_t to 64 bity w architekturze 64-bitowej, na tych architekturach wartość int pozostaje 32-bitowa).
Podsumowując: użyj size_t, aby przedstawić rozmiar obiektu i int (lub long) w innych przypadkach.
size_tTypu określa się jako unsigned integralną typu sizeofoperatora. W prawdziwym świecie często widzisz intdefinicję jako 32 bity (dla kompatybilności wstecznej), ale size_tzdefiniowaną jako 64 bity (więc możesz zadeklarować tablice i struktury o rozmiarze większym niż 4 GiB) na platformach 64-bitowych. Jeśli a long intjest również 64-bitowy, nazywa się to konwencją LP64; jeśli long intma 32 bity, ale long long intwskaźniki mają 64 bity, to jest LLP64. Możesz również otrzymać odwrotną stronę, program, który używa 64-bitowych instrukcji prędkości, ale 32-bitowych wskaźników do oszczędzania pamięci. Ponadto intjest podpisany i size_tniepodpisany.
Historycznie istniało wiele innych platform, na których adresy były szersze lub krótsze niż natywny rozmiar int. W rzeczywistości w latach 70. i na początku 80. było to bardziej powszechne niż nie: wszystkie popularne 8-bitowe mikrokomputery miały 8-bitowe rejestry i 16-bitowe adresy, a przejście między 16 a 32 bitami również tworzyło wiele maszyn, które mieli adresy szersze niż ich rejestry. Czasami wciąż widzę tutaj pytania o Borland Turbo C dla MS-DOS, którego tryb ogromnej pamięci miał 20-bitowe adresy przechowywane w 32 bitach na 16-bitowym procesorze (ale które mogą obsługiwać 32-bitowy zestaw instrukcji 80386); Motorola 68000 miała 16-bitową jednostkę ALU z 32-bitowymi rejestrami i adresami; istniały komputery mainframe IBM z 15-bitowymi, 24-bitowymi lub 31-bitowymi adresami. Nadal widzisz różne rozmiary ALU i magistrali adresowej w systemach wbudowanych.
Za każdym razem, gdy intjest mniejszy niż size_ti próbujesz zapisać rozmiar lub przesunięcie bardzo dużego pliku lub obiektu w pliku unsigned int, istnieje możliwość, że może się przepełnić i spowodować błąd. W przypadku znaku intistnieje również możliwość uzyskania liczby ujemnej. Jeśli intlub unsigned intjest szerszy, program będzie działał poprawnie, ale marnuje pamięć.
Jeśli chcesz mieć możliwość przenoszenia, na ogół powinieneś używać odpowiedniego typu do tego celu. Wiele osób poleci używanie matematyki ze znakiem zamiast bez znaku (aby uniknąć nieprzyjemnych, subtelnych błędów, takich jak 1U < -3). W tym celu Standard definiuje biblioteczne ptrdiff_tw <stddef.h>tak podpisanej typu wyniku odjęcia wskaźnik od drugiego.
To powiedziawszy, obejściem może być sprawdzenie granic wszystkich adresów i przesunięć względem INT_MAXi albo 0lub INT_MINodpowiednio, i włączenie ostrzeżeń kompilatora o porównywaniu podpisanych i niepodpisanych ilości na wypadek, gdybyś je pominął. Zawsze powinieneś zawsze sprawdzać dostęp do tablicy pod kątem przepełnienia w C.
Myślę, że size_t faktycznie jest gwarantowanym aliasem dla liczby całkowitej bez znaku, więc nie może to być struktura. Jednak w tej chwili nie mam pod ręką odniesienia, aby to potwierdzić.
zrelaksuj się
9
@unwind: C99: TC3, 7,17 §2
Christoph
1
@danio Dlaczego tak jest? Czy możesz wyjaśnić?
Rüppell's Vulture
2
Nie linkowałbym do cplusplus, gdybym był tobą! Jeśli nie możesz zacytować rozdziału, wersetu, akapitu i wiersza, to wszystko to tylko pogłoski! :-)
graham.reeds
1
size_tjest określony jako typ liczby całkowitej bez znaku . C11 §6.5.3.4 5 „Wartość wyniku obu operatorów ( sizeof_Alignof) jest zdefiniowana w ramach implementacji, a jego typ (liczba całkowita bez znaku) to size_t,”.
SIZE_Tjest ULONG_PTRreprezentowanie maksymalną liczbę bajtów, do którego wskaźnik może wskazywać.
Ten typ jest deklarowany w następujący sposób:
typedef ULONG_PTR SIZE_T;
A ULONG_PTRto typ długi bez znaku, używany do dokładności wskaźnika. Jest używany podczas rzutowania wskaźnika na długi typ w celu wykonania arytmetyki wskaźnika.
Odpowiedzi:
Z przyjaznej Wikipedii :
Sprawdź też, dlaczego rozmiar_t ma znaczenie
źródło
/usr/include/stdlib.h
pobiera definicję skąd/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
i tam jest ona ustawiona domyślnie,long unsigned int
chyba że inny plik nagłówkowy mówi inaczej.size_t to typ używany do reprezentowania rozmiarów (jak sugeruje jego nazwa). Jego platforma (a nawet potencjalnie implementacja) jest zależna i powinien być używany tylko w tym celu. Oczywiście, reprezentując rozmiar, size_t jest bez znaku. Wiele funkcji z biblioteki standardowej, w tym malloc, sizeof i różne funkcje operacji na łańcuchach, używa size_t jako typu danych.
Wartość int jest domyślnie podpisywana i chociaż jego rozmiar jest również zależny od platformy, na większości nowoczesnych maszyn będzie to stały 32-bitowy (i chociaż size_t to 64 bity w architekturze 64-bitowej, na tych architekturach wartość int pozostaje 32-bitowa).
Podsumowując: użyj size_t, aby przedstawić rozmiar obiektu i int (lub long) w innych przypadkach.
źródło
size_t
Typu określa się jako unsigned integralną typusizeof
operatora. W prawdziwym świecie często widziszint
definicję jako 32 bity (dla kompatybilności wstecznej), alesize_t
zdefiniowaną jako 64 bity (więc możesz zadeklarować tablice i struktury o rozmiarze większym niż 4 GiB) na platformach 64-bitowych. Jeśli along int
jest również 64-bitowy, nazywa się to konwencją LP64; jeślilong int
ma 32 bity, alelong long int
wskaźniki mają 64 bity, to jest LLP64. Możesz również otrzymać odwrotną stronę, program, który używa 64-bitowych instrukcji prędkości, ale 32-bitowych wskaźników do oszczędzania pamięci. Ponadtoint
jest podpisany isize_t
niepodpisany.Historycznie istniało wiele innych platform, na których adresy były szersze lub krótsze niż natywny rozmiar
int
. W rzeczywistości w latach 70. i na początku 80. było to bardziej powszechne niż nie: wszystkie popularne 8-bitowe mikrokomputery miały 8-bitowe rejestry i 16-bitowe adresy, a przejście między 16 a 32 bitami również tworzyło wiele maszyn, które mieli adresy szersze niż ich rejestry. Czasami wciąż widzę tutaj pytania o Borland Turbo C dla MS-DOS, którego tryb ogromnej pamięci miał 20-bitowe adresy przechowywane w 32 bitach na 16-bitowym procesorze (ale które mogą obsługiwać 32-bitowy zestaw instrukcji 80386); Motorola 68000 miała 16-bitową jednostkę ALU z 32-bitowymi rejestrami i adresami; istniały komputery mainframe IBM z 15-bitowymi, 24-bitowymi lub 31-bitowymi adresami. Nadal widzisz różne rozmiary ALU i magistrali adresowej w systemach wbudowanych.Za każdym razem, gdy
int
jest mniejszy niżsize_t
i próbujesz zapisać rozmiar lub przesunięcie bardzo dużego pliku lub obiektu w plikuunsigned int
, istnieje możliwość, że może się przepełnić i spowodować błąd. W przypadku znakuint
istnieje również możliwość uzyskania liczby ujemnej. Jeśliint
lubunsigned int
jest szerszy, program będzie działał poprawnie, ale marnuje pamięć.Jeśli chcesz mieć możliwość przenoszenia, na ogół powinieneś używać odpowiedniego typu do tego celu. Wiele osób poleci używanie matematyki ze znakiem zamiast bez znaku (aby uniknąć nieprzyjemnych, subtelnych błędów, takich jak
1U < -3
). W tym celu Standard definiuje biblioteczneptrdiff_t
w<stddef.h>
tak podpisanej typu wyniku odjęcia wskaźnik od drugiego.To powiedziawszy, obejściem może być sprawdzenie granic wszystkich adresów i przesunięć względem
INT_MAX
i albo0
lubINT_MIN
odpowiednio, i włączenie ostrzeżeń kompilatora o porównywaniu podpisanych i niepodpisanych ilości na wypadek, gdybyś je pominął. Zawsze powinieneś zawsze sprawdzać dostęp do tablicy pod kątem przepełnienia w C.źródło
Dzieje się tak, ponieważ size_t może być czymkolwiek innym niż int (może być strukturą). Chodzi o to, że oddziela swoje zadanie od typu podstawowego.
źródło
size_t
jest określony jako typ liczby całkowitej bez znaku . C11 §6.5.3.4 5 „Wartość wyniku obu operatorów (sizeof
_Alignof
) jest zdefiniowana w ramach implementacji, a jego typ (liczba całkowita bez znaku) tosize_t
,”.Definicja
SIZE_T
znajduje się na: https://msdn.microsoft.com/en-us/library/cc441980.aspx i https://msdn.microsoft.com/en-us/library/cc230394.aspxWklejanie tutaj wymaganych informacji:
SIZE_T
jestULONG_PTR
reprezentowanie maksymalną liczbę bajtów, do którego wskaźnik może wskazywać.Ten typ jest deklarowany w następujący sposób:
A
ULONG_PTR
to typ długi bez znaku, używany do dokładności wskaźnika. Jest używany podczas rzutowania wskaźnika na długi typ w celu wykonania arytmetyki wskaźnika.Ten typ jest deklarowany w następujący sposób:
źródło
SIZE_T
nie jestsize_t
, o co pytał OP.SIZE_T
jest zupełnie inny niżsize_t
. Nie możesz zadeklarować zmiennej typuSIZE_T
.