Câu trả lời:
Các size_t
type là kiểu integer unsigned mà là kết quả của các sizeof
nhà điều hành (và các offsetof
nhà điều hành), vì vậy nó được đảm bảo để có đủ lớn để chứa kích thước của đối tượng lớn nhất hệ thống của bạn có thể xử lý (ví dụ, một mảng tĩnh của 8Gb).
Các size_t
loại có thể được lớn hơn, bằng hoặc nhỏ hơn một unsigned int
, và trình biên dịch của bạn có thể làm cho các giả định về nó để tối ưu hóa.
Bạn có thể tìm thấy thông tin chính xác hơn trong tiêu chuẩn C99, phần 7.17, bản nháp có sẵn trên Internet ở định dạng pdf hoặc trong tiêu chuẩn C11, phần 7.19, cũng có sẵn dưới dạng bản nháp pdf .
size_t
có thể đại diện! Nếu không, ai làm?
Classic C (phương ngữ đầu tiên của C được mô tả bởi Brian Kernighan và Dennis Ritchie trong Ngôn ngữ lập trình C, Prentice-Hall, 1978) đã không cung cấp size_t
. Ủy ban tiêu chuẩn C được giới thiệu size_t
để loại bỏ một vấn đề về tính di động
Nói tóm lại, size_t
không bao giờ là tiêu cực và nó tối đa hóa hiệu suất vì nó được coi là loại số nguyên không dấu đủ lớn - nhưng không quá lớn - để biểu thị kích thước của đối tượng lớn nhất có thể trên nền tảng đích.
Kích thước không bao giờ nên âm và thực sự size_t
là một loại không dấu. Ngoài ra, vì size_t
không được ký, bạn có thể lưu trữ các số lớn gấp đôi so với loại đã ký tương ứng, bởi vì chúng ta có thể sử dụng bit dấu để biểu thị cường độ, giống như tất cả các bit khác trong số nguyên không dấu. Khi chúng tôi đạt được thêm một bit, chúng tôi sẽ nhân phạm vi số mà chúng tôi có thể đại diện cho hệ số khoảng hai.
Vì vậy, bạn hỏi, tại sao không chỉ sử dụng một unsigned int
? Nó có thể không có khả năng giữ số lượng đủ lớn. Trong một triển khai có unsigned int
32 bit, số lớn nhất có thể biểu thị là 4294967295
. Một số bộ xử lý, chẳng hạn như IP16L32, có thể sao chép các đối tượng lớn hơn 4294967295
byte.
Vì vậy, bạn hỏi, tại sao không sử dụng một unsigned long int
? Nó thực hiện một số lượng hiệu suất trên một số nền tảng. Tiêu chuẩn C yêu cầu long
chiếm ít nhất 32 bit. Một nền tảng IP16L32 thực hiện mỗi chiều dài 32 bit dưới dạng một cặp từ 16 bit. Hầu như tất cả các toán tử 32 bit trên các nền tảng này đều yêu cầu hai hướng dẫn, nếu không muốn nói là vì chúng hoạt động với 32 bit trong hai khối 16 bit. Ví dụ, di chuyển dài 32 bit thường yêu cầu hai hướng dẫn máy - một để di chuyển mỗi đoạn 16 bit.
Sử dụng size_t
để tránh hiệu suất này. Theo bài viết tuyệt vời này , "Loại size_t
là một typedef là bí danh cho một số loại số nguyên không dấu, thông thường unsigned int
hoặc unsigned long
, nhưng thậm chí có thể unsigned long long
. Mỗi triển khai C tiêu chuẩn được cho là chọn số nguyên không dấu đủ lớn - nhưng không lớn hơn cần thiết-- để thể hiện kích thước của đối tượng lớn nhất có thể trên nền tảng đích. "
unsigned int
lon và thay đổi từ hệ thống này sang hệ thống khác. Nó bắt buộc phải có ít nhất 65536
, nhưng nó phổ biến 4294967295
và có thể là 18446744073709551615
(2 ** 64-1) trên một số hệ thống.
unsigned char
). Tiêu chuẩn dường như không chứa chuỗi '65535' hoặc '65536' ở bất cứ đâu và '+32767' chỉ xảy ra (1.9: 9) trong một ghi chú là số nguyên lớn nhất có thể biểu thị trong int
; không có sự đảm bảo nào được đưa ra thậm chí INT_MAX
không thể nhỏ hơn thế!
Loại size_t là loại được trả về bởi toán tử sizeof. Nó là một số nguyên không dấu có khả năng thể hiện kích thước theo byte của bất kỳ phạm vi bộ nhớ nào được hỗ trợ trên máy chủ. Nó (thường) liên quan đến ptrdiff_t trong đó ptrdiff_t là một giá trị số nguyên đã ký sao cho sizeof (ptrdiff_t) và sizeof (size_t) bằng nhau.
Khi viết mã C, bạn phải luôn sử dụng size_t bất cứ khi nào xử lý phạm vi bộ nhớ.
Mặt khác, kiểu int được định nghĩa cơ bản là kích thước của giá trị số nguyên (đã ký) mà máy chủ có thể sử dụng để thực hiện hiệu quả nhất số học số nguyên. Ví dụ, trên nhiều máy tính loại PC cũ, giá trị sizeof (size_t) sẽ là 4 (byte) nhưng sizeof (int) sẽ là 2 (byte). Số học 16 bit nhanh hơn số học 32 bit, mặc dù CPU có thể xử lý không gian bộ nhớ (logic) lên tới 4 GiB.
Chỉ sử dụng kiểu int khi bạn quan tâm đến hiệu quả vì độ chính xác thực tế của nó phụ thuộc mạnh mẽ vào cả tùy chọn trình biên dịch và kiến trúc máy. Cụ thể, tiêu chuẩn C chỉ định các bất biến sau: sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long) không đặt ra giới hạn nào khác cho biểu diễn thực tế của độ chính xác có sẵn cho mỗi lập trình viên những kiểu nguyên thủy.
Lưu ý: Điều này KHÔNG giống như trong Java (thực tế chỉ định độ chính xác bit cho từng loại 'char', 'byte', 'short', 'int' và 'long').
size_t
có khả năng đại diện cho kích thước của bất kỳ đối tượng nào (ví dụ: số, mảng, cấu trúc). Toàn bộ phạm vi bộ nhớ có thể vượt quásize_t
size_t
- Tôi hy vọng bạn không có ý đó. Hầu hết thời gian chúng tôi không xử lý các mảng trong đó tính chính xác của không gian địa chỉ + tính di động thậm chí còn quan trọng. Trong những trường hợp này, bạn sẽ thực hiện size_t
. Trong mọi trường hợp khác, bạn lấy các chỉ số ra khỏi số nguyên (đã ký). Bởi vì sự nhầm lẫn (không có cảnh báo) phát sinh từ hành vi ngầm không được xem xét của dấu không dấu là phổ biến hơn và tồi tệ hơn các vấn đề về tính di động có thể phát sinh trong các trường hợp khác.
Nhập size_t phải đủ lớn để lưu trữ kích thước của bất kỳ đối tượng nào có thể. Unsign int không phải đáp ứng điều kiện đó.
Ví dụ: trong hệ thống 64 bit int và unsign int có thể rộng 32 bit, nhưng size_t phải đủ lớn để lưu trữ số lớn hơn 4G
size_t
sẽ chỉ phải lớn như vậy nếu trình biên dịch có thể chấp nhận loại X sao cho sizeof (X) sẽ mang lại giá trị lớn hơn 4G. Hầu hết các trình biên dịch sẽ từ chối typedef unsigned char foo[1000000000000LL][1000000000000LL]
, ví dụ , và thậm chí foo[65536][65536];
có thể bị từ chối một cách hợp pháp nếu vượt quá giới hạn được xác định theo tài liệu.
Đoạn trích từ hướng dẫn sử dụng glibc 0,02 cũng có thể có liên quan khi nghiên cứu chủ đề:
Có một vấn đề tiềm ẩn với loại size_t và các phiên bản của GCC trước khi phát hành 2.4. ANSI C yêu cầu size_t luôn là loại không dấu. Để tương thích với các tệp tiêu đề của hệ thống hiện tại, GCC định nghĩa size_t trong stddef.h' to be whatever type the system's
sys / type.h 'định nghĩa nó là. Hầu hết các hệ thống Unix định nghĩa size_t trong `sys / type.h ', định nghĩa nó là một kiểu đã ký. Một số mã trong thư viện phụ thuộc vào size_t là loại không dấu và sẽ không hoạt động chính xác nếu nó được ký.
Mã thư viện GNU C dự kiến size_t không được ký là chính xác. Định nghĩa của size_t là một loại đã ký là không chính xác. Chúng tôi dự định trong phiên bản 2.4, GCC sẽ luôn xác định size_t là loại không dấu và fixincludes' script will massage the system's
sys / type.h 'để không xung đột với điều này.
Trong khi đó, chúng tôi giải quyết vấn đề này bằng cách thông báo rõ ràng cho GCC sử dụng loại không dấu cho size_t khi biên dịch thư viện GNU C. `configure 'sẽ tự động phát hiện loại GCC sử dụng cho size_t sắp xếp để ghi đè nó nếu cần thiết.
Nếu trình biên dịch của tôi được đặt thành 32 bit, size_t
không có gì khác ngoài typedef cho unsigned int
. Nếu trình biên dịch của tôi được đặt thành 64 bit, size_t
không có gì khác ngoài typedef cho unsigned long long
.
unsigned long
cho cả hai trường hợp trên một số hệ điều hành.
size_t là kích thước của một con trỏ.
Vì vậy, trong 32 bit hoặc mô hình IL_t32 (số nguyên, dài, con trỏ) chung size_t là 32 bit. và trong 64 bit hoặc mô hình LP_t (dài, con trỏ) phổ biến size_t là 64 bit (số nguyên vẫn là 32 bit).
Có những mô hình khác nhưng đây là những mô hình mà g ++ sử dụng (ít nhất là theo mặc định)
size_t
không nhất thiết phải có cùng kích thước với một con trỏ, mặc dù nó thường là vậy. Một con trỏ phải có khả năng trỏ đến bất kỳ vị trí nào trong bộ nhớ; size_t
chỉ phải đủ lớn để thể hiện kích thước của vật thể lớn nhất.