Sự khác biệt giữa size_t và std :: size_t


139

Sự khác biệt giữa size_tstd::size_tvề nơi chúng được khai báo, khi nào chúng nên được sử dụng và bất kỳ tính năng khác biệt nào khác?


Tôi muốn biết liệu thông số C ++ có liên kết std :: size_t với loại C size_t không.
Doug T.

Xem câu hỏi tương tự: link
Mankude

Câu trả lời:


88

C size_ts và C ++ ' std::size_tđều giống nhau.

Trong C, nó được định nghĩa trong <stddef.h>và trong C ++, được định nghĩa trong <cstddef>đó có nội dung giống với tiêu đề C (xem trích dẫn bên dưới). Nó được định nghĩa là kiểu số nguyên không dấu của kết quả của toán tử sizeof .

Tiêu chuẩn C nói trong §17.7 / 2,

size_t là kiểu số nguyên không dấu của kết quả của toán tử sizeof

Và C ++ Standard cho biết (về cstddeftiêu đề) trong §18.1 / 3,

Nội dung giống như tiêu đề thư viện C tiêu chuẩn, với các thay đổi sau .

Vì vậy, yeah, cả hai đều giống nhau; sự khác biệt duy nhất là C ++ định nghĩa size_ttrong stdkhông gian tên.

Cũng xin lưu ý rằng dòng trên cũng nói "với những thay đổi sau" không được đề cập đến size_t. Nó khá liên quan đến các bổ sung mới (chủ yếu) được tạo bởi C ++ vào ngôn ngữ (không có trong C) cũng được định nghĩa trong cùng một tiêu đề.


Wikipedia có thông tin rất tốt về phạm vi và kích thước lưu trữ của size_t:

Phạm vi và kích thước lưu trữ của size_t

Các thực tế loại size_t là nền tảng phụ thuộc ; 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, [3] [4] khi chuyển từ kiến ​​trúc 32 sang 64 bit chẳng hạn.

Theo tiêu chuẩn ISO C năm 1999 (C99), size_t là loại số nguyên không dấu có ít nhất 16 bit.

Và phần còn lại bạn có thể đọc từ trang này tại wikipedia.


Điều đó mang đến một Q khác, Nếu STL đã nhập size_t thông qua C (cstddef) thì tại sao nó lại có phiên bản khác của riêng mình?
Alok Lưu

43
@Als: Nói đúng ra, đó là lỗi khi nói size_tkhông có using namespace std;hoặc using std::size_t;. Tuy nhiên, hầu hết các trình biên dịch cho phép nó và Tiêu chuẩn đặc biệt cho phép họ cho phép nó (§D.5 / 3).
Potatoswatter

9
@Potatoswatter: Chắc chắn đó không thể là một lỗi và được cho phép cụ thể trong tiêu chuẩn? Nếu nó ở trong tiêu chuẩn, đó không phải là một lỗi!
Ben Hymers

8
@BenHymers Tiêu chuẩn chỉ định những gì các tiêu đề tiêu chuẩn khai báo và chúng không được phép khai báo bất kỳ tên không dành riêng nào khác. Tiêu đề <cstddef>có thể hoặc không thể khai báo ::size_t, vì vậy bạn không thể dựa vào nó ở đó hoặc vắng mặt, trừ khi cụ thể bao gồm <stddef.h>hoặc một tiêu đề khác từ thư viện C được đảm bảo để khai báo.
Potatoswatter

4
@Potatoswatter: Ah, tôi hiểu ý của bạn bây giờ! Tôi đã phải bối rối bởi quá nhiều "cho phép" trong một câu. Tôi vẫn nghĩ rằng nhận xét đầu tiên của bạn là quá mạnh; như bạn vừa nói, ::size_tcó mặt, ví dụ như trong <stddef.h>, vì vậy bạn không cần phải luôn luôn đủ điều kiện std::.
Ben Hymers

16

Từ C ++ 03 "17.4.3.1.4 Các loại":

Đối với mỗi loại T từ thư viện C chuẩn (chú thích 169), các loại :: T và std :: T được dành riêng cho việc triển khai và khi được xác định, :: T sẽ giống hệt với std :: T.

Và chú thích 169:

Các loại này là clock_t, div_t, FILE, fpose_t, lconv, ldiv_t, mbstate_t, ptrdiff_t, sig_atomic_t, size_t, time_t, tm, va_list, wctrans_t, wctype_t, và wint.


Vì vậy, mã di động không nên dựa vào các std::Tbiến thể được xác định?
Mankude

5
@Mankude: Bạn không nên dựa vào chúng được xác định nếu bạn chỉ bao gồm phiên bản C của tiêu đề tương ứng. Nếu bạn #include <stddef.h>sau đó std::size_tcó thể hoặc có thể không có sẵn. Nếu bạn #include <cstddef>sau đó std::size_tcó sẵn, nhưng size_tcó thể không.
Dennis Zickefoose

4
@Mankude: Các mặt đối diện. Các phiên bản C ++ của các tiêu đề phải xác định chúng trong std::và đoạn nói rằng nó cũng có thể định nghĩa chúng trong không gian tên cấp cao nhất và nếu có, nó phải xác định chúng theo std::cấp độ và cấp cao nhất. Hầu hết các trình biên dịch chỉ bao gồm tiêu đề C và nhập tên vào std::, vì vậy các ký hiệu cuối cùng được xác định trong cả hai.
Jan Hudec

4
Cá nhân, tôi không bao giờ bận tâm với các tiêu đề <cxxxxx> hoặc các std::biến thể của số nhận dạng đến từ bờ C. Tôi gắn bó với <xxxxx.h>các tiêu đề C tiêu chuẩn - nó không bao giờ là vấn đề. Vì vậy, tôi muốn sử dụng <stddef.h>size_tvà không bao giờ bỏ một ý nghĩ thứ hai để std::size_t; thật ra, tôi không bao giờ nghĩ rằng có (hoặc có thể) a std::size_t.
Michael Burr

12

std :: size_t trên thực tế là size_t của stddef.h .

cstddef đưa ra như sau:

#include <stddef.h>
namespace std 
{
  using ::ptrdiff_t;
  using ::size_t;
}

... có hiệu quả đưa định nghĩa trước đó vào không gian tên std.


Như Nawaz chỉ ra, nó thực sự là cách khác. Bạn không thể bao gồm <cstddef>và mong đợi để có được ::size_t, nhưng nếu bạn bao gồm <stddef.h>bạn sẽ nhận được std::size_t.
MSalters

4
@MSalters, tôi không theo dõi. Bao gồm <stddef.h>sẽ chỉ có được bạn ::size_t.
hifier

2
Đó là một lỗi trong việc thực hiện của bạn, sau đó.
MSalters

4
@MSalters, tôi không theo dõi lắm. Nó không phải là cách khác? <cstddef> xuất phát từ C ++, do đó, nên xác định nội dung trong std :: *? Mặt khác, trong một tiêu đề C, như stddef.h, tôi chỉ mong đợi loại C, tức là :: size_t.
Ela782

11
@MSalters, vì C ++ 11 không chính xác. Nếu bạn bao gồm <cstddef>bạn được đảm bảo để có được std::size_tvà bạn cũng có thể nhận được ::size_t(nhưng nó không được bảo đảm). Nếu bạn bao gồm <stddef.h>bạn được đảm bảo để có được ::size_tvà bạn cũng có thể nhận được std::size_t(nhưng nó không được bảo đảm). Nó khác với C ++ 03 nhưng điều đó thực sự không thể thực hiện được và được sửa là một khiếm khuyết.
Jonathan Wakely
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.