Sự khác biệt giữa size_t và int trong C ++ là gì?


173

Trong một số ví dụ về C ++, tôi thấy việc sử dụng kiểu size_tmà 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_tnên tốt hơn?


3
Để biết ví dụ thực tế khi chúng không thể thay thế cho nhau, hãy xem một câu hỏi tôi đã hỏi trước đây: stackoverflow.com/questions/645168/ mẹo
Tyler McHenry

Câu trả lời:


153

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


76
Và như vậy, size_t là gì?
NDEthos

8
@NDEthos Nó phụ thuộc! Ở đây, Linux /usr/include/stdlib.hcó đị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 inttrừ khi một số tệp tiêu đề khác nói khác.
David Tonhofer

1
Tôi xác nhận size_t để int tuncation là nguy hiểm . Điều này có thể không đúng chủ đề, nhưng làm thế nào để viết một bản vá để sửa lỗi đó khi nó xảy ra hàng ngàn lần trong kernel linux?
dùng2284570

36

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.


12

Các size_tloại được định nghĩa là loại không thể thiếu unsigned của sizeofnhà đ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 intcũng là 64 bit, đây được gọi là quy ước LP64; nếu long intlà 32 bit nhưng long long intvà 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 intnhỏ hơn size_tvà 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 inthoặc unsigned intrộ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_ttrong <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 0hoặc INT_MINnế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.


8

Đó 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.


8
Tôi nghĩ size_t thực sự được đảm bảo là bí danh cho một số nguyên không dấu, vì vậy nó không thể là một cấu trúc. Mặc dù vậy, tôi không có tài liệu tham khảo để sao lưu điều này ngay bây giờ.
thư giãn

9
@unwind: C99: TC3, 7.17 §2
Christoph

1
@danio Tại sao lại như vậy? Bạn có thể giải thích?
Kền kền Rüppell

2
Tôi sẽ không liên kết với cplusplus nếu tôi là bạn! Nếu bạn không thể trích dẫn chương, câu, đoạn và dòng thì tất cả chỉ là tin đồn! :-)
graham.reeds

1
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,".
chux - Tái lập Monica 7/07/2015

-1

Định nghĩa của SIZE_Tđược tìm thấy tại: https://msdn.microsoft.com/en-us/l Library / cc441980.aspxhttps://msdn.microsoft.com/en-us/l Library / cc230394.aspx

Dán ở đây các thông tin cần thiết:

SIZE_Tlà 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_PTRlà 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;

2
SIZE_TKhông size_t, những gì OP hỏi về.
ikegami

2
Đó là một phần mở rộng của Microsoft, không phải là một phần của ngôn ngữ tiêu chuẩn.
Davislor

SIZE_Tlà 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.
calocedrus
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.