ความแตกต่างระหว่าง size_t และ std :: size_t


139

อะไรคือความแตกต่างระหว่างsize_tและstd::size_tในแง่ของที่พวกเขาจะประกาศเมื่อใดที่พวกเขาควรจะใช้และคุณสมบัติที่แตกต่างอื่น ๆ ?


ฉันสนใจที่จะทราบว่าการเชื่อมโยงข้อมูลจำเพาะของ C ++ std :: size_t ไปยังประเภท C size_t หรือไม่
Doug T.

ดูคำถามที่คล้ายกัน: ลิงค์
Mankarse

คำตอบ:


88

C size_tและ C ++ std::size_tเหมือนกันทั้งคู่

ใน C มันถูกกำหนดไว้ใน<stddef.h>และใน C ++ มันถูกกำหนดไว้ใน<cstddef>เนื้อหาที่เป็นเช่นเดียวกับส่วนหัว C (ดูใบเสนอราคาด้านล่าง) ที่กำหนดไว้ในฐานะที่เป็นชนิดจำนวนเต็มไม่ได้ลงนามในผลของsizeofผู้ประกอบการ

C Standard กล่าวใน§17.7 / 2

size_t ซึ่งเป็นประเภทเลขจำนวนเต็มที่ไม่ได้ลงนามของผลลัพธ์ของตัวดำเนินการsizeof

และมาตรฐาน C ++ บอกว่า (ประมาณcstddefส่วนหัว) ใน§18.1 / 3

เนื้อหาเป็นเช่นเดียวกับส่วนหัวของห้องสมุดมาตรฐาน C, กับการเปลี่ยนแปลงดังต่อไปนี้

ดังนั้นใช่ทั้งคู่เหมือนกัน ข้อแตกต่างเพียงอย่างเดียวคือ C ++ กำหนดsize_tในstdเนมสเปซ

โปรดแจ้งให้ทราบว่าเส้นดังกล่าวข้างต้นนอกจากนี้ยังกล่าวว่า"กับการเปลี่ยนแปลงต่อไป"size_tซึ่งไม่ได้หมายถึง มันค่อนข้างหมายถึงการเพิ่มใหม่ (ส่วนใหญ่) ทำโดย C ++ เป็นภาษา (ไม่อยู่ใน C) ซึ่งจะถูกกำหนดไว้ในส่วนหัวเดียวกัน


Wikipedia มีข้อมูลที่ดีมากเกี่ยวกับช่วงและขนาดการเก็บข้อมูล size_t:

ช่วงและขนาดการจัดเก็บของ size_t

จริงประเภทของ size_t คือ ขึ้นอยู่กับแพลตฟอร์ม ; ผิดพลาด คือการสมมติ size_t เป็นเช่นเดียวกับ int ไม่ได้ลงนามซึ่งสามารถนำไปสู่การเขียนโปรแกรมข้อผิดพลาด [3] [4] เมื่อย้ายจาก 32 สถาปัตยกรรม 64 บิตตัวอย่างเช่น

ตามมาตรฐาน ISO 1999 C (C99) size_t เป็นประเภทจำนวนเต็มที่ไม่ได้ลงนามอย่างน้อย 16 บิต

และที่เหลือคุณสามารถอ่านจากหน้านี้ได้ที่วิกิพีเดีย


นั่นนำไปสู่อีก Q ถ้า STL นำเข้า size_t ผ่าน C (cstddef) แล้วทำไมมันถึงมีเวอร์ชั่นอื่นเป็นของตัวเองอีกครั้ง?
Alok บันทึก

43
@Als: พูดอย่างเคร่งครัดมันเป็นข้อผิดพลาดจะพูดsize_tโดยไม่ได้หรือusing namespace std; using std::size_t;อย่างไรก็ตามคอมไพเลอร์ส่วนใหญ่อนุญาตให้ทำได้และมาตรฐานอนุญาตให้พวกเขาอนุญาตเฉพาะ (§D.5 / 3)
Potatoswatter

9
@Potatoswatter: แน่นอนมันไม่สามารถเป็นทั้งข้อผิดพลาดและได้รับอนุญาตโดยเฉพาะในมาตรฐานหรือไม่ หากเป็นมาตรฐานก็ไม่ใช่ข้อผิดพลาด!
เบ็นไฮเมอร์ส

8
@BenHymers มาตรฐานระบุสิ่งที่ส่วนหัวมาตรฐานประกาศและพวกเขาไม่ได้รับอนุญาตให้ประกาศชื่อที่ไม่ได้จองไว้อื่น ๆ ส่วนหัว<cstddef>อาจหรืออาจไม่ประกาศ::size_tดังนั้นคุณจึงไม่สามารถพึ่งพาได้ว่าอยู่ที่นั่นหรือไม่อยู่เว้นแต่ว่าจะรวมถึง<stddef.h>หรือส่วนหัวอื่น ๆ จากไลบรารี C ซึ่งรับประกันว่าจะประกาศ
Potatoswatter

4
@Potatoswatter: อ้าฉันเห็นแล้วว่าคุณหมายถึงอะไร! ฉันต้องสับสนโดย "อนุญาต" มากเกินไปในหนึ่งประโยค ฉันยังคิดว่าความคิดเห็นแรกของคุณแข็งแกร่งเกินไป ตามที่คุณเพิ่งพูด::size_tมีอยู่เช่นใน<stddef.h>ดังนั้นคุณไม่จำเป็นต้องมีคุณสมบัติด้วยstd::เสมอ
เบ็นไฮเมอร์ส

16

จาก C ++ 03 "17.4.3.1.4 ประเภท":

สำหรับแต่ละประเภท T จากไลบรารี C มาตรฐาน (เชิงอรรถ 169), ประเภท :: T และ std :: T จะถูกสงวนไว้สำหรับการนำไปใช้และเมื่อกำหนดแล้ว :: T จะเหมือนกับ std :: T

และเชิงอรรถ 169:

ชนิดเหล่านี้คือ clock_t, div_t, FILE, fpos_t, lconv, ldiv_t, mbstate_t, ptrdiff_t, sig_atomic_t, size_t, time_t, tm, vct_t, wctrans_t, wctrans_t และ wint_t


ดังนั้นรหัสแบบพกพาไม่ควรขึ้นอยู่กับstd::Tตัวแปรที่กำหนดไว้?
Mankarse

5
@Mankarse: คุณไม่ควรพึ่งพามันที่ถูกกำหนดไว้หากคุณรวมเฉพาะเวอร์ชั่น C ของส่วนหัวที่เกี่ยวข้อง หากคุณ#include <stddef.h>แล้วstd::size_tอาจจะหรืออาจจะไม่สามารถใช้ได้ หากคุณ#include <cstddef>แล้วstd::size_tสามารถใช้ได้ แต่size_tอาจจะไม่ได้
Dennis Zickefoose

4
@Mankarse: oposite ส่วนหัวของเวอร์ชัน C ++ ต้องกำหนดไว้ในส่วนstd::และย่อหน้าบอกว่ามันอาจกำหนดไว้ในเนมสเปซระดับบนสุดและหากเป็นเช่นนั้นจะต้องกำหนดให้เหมือนกันในstd::ระดับบนสุด คอมไพเลอร์ส่วนใหญ่มีเพียงส่วนหัว C และนำเข้าชื่อstd::ดังนั้นสัญลักษณ์จะถูกกำหนดในทั้งสอง
Jan Hudec

4
โดยส่วนตัวฉันไม่เคยรำคาญกับส่วนหัว <cxxxxx> หรือstd::ตัวแปรของตัวระบุที่มาจากฝั่ง C ฉันติดกับ<xxxxx.h>ส่วนหัว C มาตรฐาน - มันไม่เคยมีปัญหา ดังนั้นฉันต้องการใช้<stddef.h>และsize_tและไม่เคยให้ความคิดที่สองที่จะstd::size_t; ในความเป็นจริงมันไม่เคยข้ามใจของฉันที่มี std::size_t(หรืออาจจะมีบริการ)
Michael Burr

12

มาตรฐาน :: size_tในความเป็นจริงstddef.h 's size_t

cstddefให้สิ่งต่อไปนี้:

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

... นำคำจำกัดความก่อนหน้านี้เข้าสู่เนมสเปซอย่างมีประสิทธิภาพ


ในขณะที่นาวาซชี้ให้เห็นจริง ๆ แล้วมันเป็นวิธีอื่น คุณไม่สามารถรวม<cstddef>และคาดว่าจะได้รับ::size_tแต่ถ้าคุณรวมถึงคุณจะได้รับ<stddef.h> std::size_t
MSalters

4
@MSalters ฉันไม่ได้ติดตาม รวมถึง<stddef.h>จะได้รับคุณ::size_tเท่านั้น
hifier

2
นั่นคือข้อผิดพลาดในการใช้งานของคุณแล้ว
MSalters

4
@MSalters ฉันไม่ค่อยติดตาม มันควรจะเป็นวิธีอื่นที่ไม่ใช่หรือ? <cstddef> มาจาก C ++ ดังนั้นควรกำหนดเนื้อหาใน std :: *? ในอีกทางหนึ่งในส่วนหัว C เช่น stddef.h ฉันคาดหวังเพียงประเภท C คือ :: size_t
Ela782

11
@MSalters เนื่องจาก C ++ 11 นั้นไม่ถูกต้อง หากคุณรวม<cstddef>คุณจะได้รับการรับประกันstd::size_tและคุณอาจได้รับ::size_t(แต่ไม่รับประกัน) หากคุณรวม<stddef.h>คุณรับประกันว่าจะได้รับ::size_tและคุณอาจได้รับstd::size_t(แต่ไม่รับประกัน) มันแตกต่างใน C ++ 03 แต่มันไม่สามารถใช้งานได้อย่างมีประสิทธิภาพและแก้ไขเป็นข้อบกพร่อง
Jonathan Wakely
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.