Trong một số ví dụ về C ++, tôi thấy việc sử dụng kiểu size_t
mà tôi sẽ sử dụng một cách đơn giản int
. Sự khác biệt là gì, và tại sao size_t
nên tốt hơn?
Trong một số ví dụ về C ++, tôi thấy việc sử dụng kiểu size_t
mà tôi sẽ sử dụng một cách đơn giản int
. Sự khác biệt là gì, và tại sao size_t
nên tốt hơn?
Câu trả lời:
Từ Wikipedia thân thiện :
Các tệp tiêu đề stdlib.h và stddef.h xác định một kiểu dữ liệu được gọi là size_t được sử dụng để thể hiện kích thước của một đối tượng. Các hàm thư viện có kích thước dự kiến chúng có kiểu size_t và toán tử sizeof ước tính thành size_t.
Loại size_t thực tế phụ thuộc vào nền tảng; một lỗi phổ biến là giả sử size_t giống như int unsign, điều này có thể dẫn đến lỗi lập trình, đặc biệt khi kiến trúc 64 bit trở nên phổ biến hơn.
Ngoài ra, hãy kiểm tra Tại sao size_t quan trọng
/usr/include/stdlib.h
có định nghĩa từ /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
đó và mặc định nó được mặc định long unsigned int
trừ khi một số tệp tiêu đề khác nói khác.
size_t là loại được sử dụng để thể hiện kích thước (như tên của nó ngụ ý). Nền tảng của nó (và thậm chí có khả năng thực hiện) phụ thuộc và chỉ nên được sử dụng cho mục đích này. Rõ ràng, đại diện cho một kích thước, size_t là không dấu. Nhiều hàm stdlib, bao gồm malloc, sizeof và các hàm hoạt động chuỗi khác nhau sử dụng size_t làm kiểu dữ liệu.
Một int được ký theo mặc định và mặc dù kích thước của nó cũng phụ thuộc vào nền tảng, nó sẽ là 32 bit cố định trên hầu hết các máy hiện đại (và mặc dù size_t là 64 bit trên kiến trúc 64 bit, int vẫn dài 32 bit trên các kiến trúc đó).
Để tóm tắt: sử dụng size_t để thể hiện kích thước của một đối tượng và int (hoặc dài) trong các trường hợp khác.
Các size_t
loại được định nghĩa là loại không thể thiếu unsigned của sizeof
nhà điều hành. Trong thế giới thực, bạn sẽ thường thấy int
được xác định là 32 bit (để tương thích ngược) nhưng size_t
được xác định là 64 bit (để bạn có thể khai báo các mảng và cấu trúc có kích thước hơn 4 GiB) trên nền tảng 64 bit. Nếu a long int
cũng là 64 bit, đây được gọi là quy ước LP64; nếu long int
là 32 bit nhưng long long int
và con trỏ là 64 bit, đó là LLP64. Bạn cũng có thể nhận được điều ngược lại, một chương trình sử dụng các hướng dẫn 64 bit cho tốc độ, nhưng con trỏ 32 bit để tiết kiệm bộ nhớ. Ngoài ra, đã int
được ký vàsize_t
không dấu.
Trước đây, có một số nền tảng khác có địa chỉ rộng hơn hoặc ngắn hơn kích thước gốc int
. Trên thực tế, trong thập niên 70 và đầu thập niên 80, điều này phổ biến hơn không phải: tất cả các máy vi tính 8 bit phổ biến đều có thanh ghi 8 bit và địa chỉ 16 bit, và quá trình chuyển đổi giữa 16 và 32 bit cũng tạo ra nhiều máy. có địa chỉ rộng hơn đăng ký của họ. Thỉnh thoảng tôi vẫn thấy các câu hỏi ở đây về Borland Turbo C cho MS-DOS, chế độ bộ nhớ khổng lồ có địa chỉ 20 bit được lưu trữ trong 32 bit trên CPU 16 bit (nhưng có thể hỗ trợ tập lệnh 32 bit của 80386); Motorola 68000 có ALU 16 bit với các thanh ghi và địa chỉ 32 bit; có các máy tính lớn của IBM với các địa chỉ 15 bit, 24 bit hoặc 31 bit. Bạn cũng vẫn thấy các kích thước ALU và bus địa chỉ khác nhau trong các hệ thống nhúng.
Bất kỳ thời gian nào int
nhỏ hơn size_t
và bạn cố gắng lưu trữ kích thước hoặc phần bù của một tệp hoặc đối tượng rất lớn trong một unsigned int
, có khả năng nó có thể tràn và gây ra lỗi. Với một int
, cũng có khả năng nhận được một số âm. Nếu một int
hoặc unsigned int
rộng hơn, chương trình sẽ chạy chính xác nhưng lãng phí bộ nhớ.
Bạn thường nên sử dụng đúng loại cho mục đích nếu bạn muốn tính di động. Rất nhiều người sẽ khuyên bạn nên sử dụng toán đã ký thay vì không dấu (để tránh những lỗi khó chịu, tinh tế như 1U < -3
). Vì mục đích đó, các định nghĩa thư viện chuẩn ptrdiff_t
trong <stddef.h>
như các loại ký về kết quả trừ đi một con trỏ từ khác.
Điều đó nói rằng, một cách giải quyết có thể là giới hạn - kiểm tra tất cả các địa chỉ và giá trị chống lại INT_MAX
và một trong hai 0
hoặc INT_MIN
nếu thích hợp, và bật cảnh báo trình biên dịch về so sánh chữ ký và số lượng unsigned trong trường hợp bạn bỏ lỡ bất kỳ. Bạn nên luôn luôn, luôn luôn, luôn luôn kiểm tra truy cập mảng của bạn xem có bị tràn trong C không.
Đó là bởi vì size_t có thể là bất cứ thứ gì khác ngoài int (có thể là struct). Ý tưởng là nó tách riêng công việc của nó từ loại cơ bản.
size_t
được chỉ định là một kiểu số nguyên không dấu . C11 §6.5.3.4 5 "Giá trị kết quả của cả hai toán tử ( sizeof
_Alignof
) được xác định theo thực hiện và loại của nó (một kiểu số nguyên không dấu) là size_t
,".
Định nghĩa của SIZE_T
được tìm thấy tại:
https://msdn.microsoft.com/en-us/l Library / cc441980.aspx và https://msdn.microsoft.com/en-us/l Library / cc230394.aspx
Dán ở đây các thông tin cần thiết:
SIZE_T
là một ULONG_PTR
đại diện cho số byte tối đa mà con trỏ có thể trỏ tới.
Loại này được khai báo như sau:
typedef ULONG_PTR SIZE_T;
A ULONG_PTR
là một loại dài không dấu được sử dụng cho độ chính xác của con trỏ. Nó được sử dụng khi truyền một con trỏ thành một loại dài để thực hiện số học con trỏ.
Loại này được khai báo như sau:
typedef unsigned __int3264 ULONG_PTR;
SIZE_T
Không size_t
, những gì OP hỏi về.
SIZE_T
là hoàn toàn khác với size_t
. Bạn không thể khai báo một biến loại SIZE_T
.