เหตุใด sizeof จึงถือว่าเป็นตัวดำเนินการ


95

เหตุใดจึงsizeofถือว่าเป็นตัวดำเนินการและไม่ใช่ฟังก์ชัน

คุณสมบัติใดบ้างที่จำเป็นในการเป็นผู้ดำเนินการ

คำตอบ:


183

เนื่องจากมาตรฐาน C บอกอย่างนั้นและได้รับการโหวตเพียงอย่างเดียว

ผลที่ตามมา:

  • ตัวถูกดำเนินการของ sizeof สามารถเป็นประเภทวงเล็บsizeof (int)แทนนิพจน์อ็อบเจ็กต์
  • ไม่จำเป็นต้องใส่วงเล็บ: ใช้ได้int a; printf("%d\n", sizeof a);ดี พวกเขากำลังเห็นบ่อยแรกเพราะพวกเขากำลังจำเป็นต้องเป็นส่วนหนึ่งของการแสดงออกประเภทหล่อและประการที่สองเพราะ sizeof มีลำดับความสำคัญสูงมากจึงไม่ได้เช่นเดียวกับsizeof a + b sizeof (a+b)แต่ไม่ได้เป็นส่วนหนึ่งของการเรียกใช้ sizeof แต่เป็นส่วนหนึ่งของตัวถูกดำเนินการ
  • คุณไม่สามารถใช้ที่อยู่ของ sizeof
  • นิพจน์ซึ่งเป็นตัวถูกดำเนินการของ sizeof ไม่ได้รับการประเมินที่รันไทม์ ( sizeof a++ไม่แก้ไข a)
  • นิพจน์ซึ่งเป็นตัวถูกดำเนินการของ sizeof สามารถมีประเภทใดก็ได้ยกเว้น void หรือประเภทฟังก์ชัน นั่นคือจุดสำคัญของขนาด

ฟังก์ชันจะแตกต่างกันในทุกประเด็น อาจมีความแตกต่างอื่น ๆ ระหว่างฟังก์ชันและตัวดำเนินการยูนารี แต่ฉันคิดว่านั่นเพียงพอแล้วที่จะแสดงให้เห็นว่าทำไม sizeof จึงไม่สามารถเป็นฟังก์ชันได้แม้ว่าจะมีเหตุผลที่ต้องการให้เป็น


3
ว้าวฉันคิดอะไรอยู่!
crashmstr

7
ไม่พูดเลยดีกว่า
Clement Herreman

ฉันเชื่อว่าทุกวันนี้สิ่งต่าง ๆ มีความซับซ้อนมากขึ้นเนื่องจากอาร์เรย์ที่มีความยาวผันแปร (VLA) IIRC มาตรฐานจะอนุญาตให้sizeofมีผลข้างเคียงหากมี VLA อยู่ในนิพจน์
Aaron McDaid

@glglgl ไม่นั่นไม่สมเหตุสมผลเลย ในบริบท(int)นั้นไม่มีอะไรน่าสนใจเพียงแค่ชื่อประเภทที่อยู่ในวงเล็บ วงเล็บต่อไปนี้เป็นส่วนหนึ่งของไวยากรณ์sizeof- จำเป็นเมื่อรับขนาดของประเภท แต่ไม่จำเป็นเมื่อรับขนาดของนิพจน์ ดูเช่นที่นี่
anatolyg

1
มาตรฐานใช้สองสัญกรณ์สำหรับsizeof: sizeof unary-expressionและsizeof ( type-name )- ดังนั้นในมาตรฐาน C11 จึงไม่ถือว่าเป็น 'cast' แต่เป็นชื่อประเภทในวงเล็บ ผลสุทธิมากเหมือนกัน (สำหรับการเปรียบเทียบการแสดงออกของนักแสดงคือ( type-name ) cast-expression) และฉันเกลียดวิธีที่ความคิดเห็น Markdown ทำงานแตกต่างจาก Q&A Markdown!
Jonathan Leffler

24

สามารถใช้เป็นค่าคงที่เวลาคอมไพล์ซึ่งเป็นไปได้ก็ต่อเมื่อเป็นตัวดำเนินการแทนที่จะเป็นฟังก์ชัน ตัวอย่างเช่น:

union foo {
    int i;
    char c[sizeof(int)];
};

ในทางไวยากรณ์หากไม่ใช่ตัวดำเนินการก็จะต้องเป็นมาโครตัวประมวลผลล่วงหน้าเนื่องจากฟังก์ชันไม่สามารถใช้ประเภทเป็นอาร์กิวเมนต์ได้ นั่นจะเป็นมาโครที่ยากในการนำไปใช้เนื่องจากsizeofสามารถใช้ทั้งชนิดและตัวแปรเป็นอาร์กิวเมนต์ได้


4
+1 แต่โปรดทราบว่าไม่ใช่ค่าคงที่เวลาคอมไพล์เมื่ออาร์กิวเมนต์เป็นอาร์เรย์ความยาวตัวแปร VLA
Jonathan Leffler

6

เนื่องจากมาตรฐาน C บอกอย่างนั้นและได้รับการโหวตเพียงอย่างเดียว

และมาตรฐานน่าจะถูกต้องเพราะsizeofใช้ประเภทและ

โดยทั่วไปถ้าโดเมนหรือโคโดเมน (หรือทั้งสองอย่าง) ของฟังก์ชันมีองค์ประกอบที่ซับซ้อนกว่าจำนวนจริงอย่างมีนัยสำคัญฟังก์ชันนั้นจะเรียกว่าตัวดำเนินการ ในทางกลับกันหากทั้งโดเมนหรือโคโดเมนของฟังก์ชันไม่มีองค์ประกอบที่ซับซ้อนกว่าจำนวนจริงฟังก์ชันนั้นน่าจะเรียกง่ายๆว่าฟังก์ชัน ฟังก์ชันตรีโกณมิติเช่นโคไซน์เป็นตัวอย่างของกรณีหลัง

นอกจากนี้เมื่อมีการใช้ฟังก์ชันบ่อยจนมีการพัฒนาสัญกรณ์ได้เร็วขึ้นหรือง่ายกว่ารูปแบบ F (x, y, z, ... ) ทั่วไปรูปแบบพิเศษที่ได้จะเรียกอีกอย่างว่าตัวดำเนิน ตัวอย่าง ได้แก่ ตัวดำเนินการ infix เช่นการบวก "+" และการหาร "/" และตัวดำเนินการ postfix เช่นแฟกทอเรียล "!" การใช้งานนี้ไม่เกี่ยวข้องกับความซับซ้อนของเอนทิตีที่เกี่ยวข้อง

(วิกิพีเดีย)


สิ่งนี้อาจอธิบายถึงแรงจูงใจของมาตรฐาน C (และภาษาโปรแกรมอื่น ๆ ) ในการใช้คำว่า "ตัวดำเนินการ" และ "ฟังก์ชัน" ตามที่พวกเขาทำ
Steve Jessop

5

เพราะไม่ใช่หน้าที่. คุณสามารถใช้มันได้ดังนี้:

int a;
printf("%d\n", sizeof a);

ฟังก์ชันมีจุดเข้าใช้งานรหัส ฯลฯ ฟังก์ชันจะถูกเรียกใช้ที่รันไทม์ (หรืออินไลน์) ต้องกำหนดขนาดของเวลาในการคอมไพล์


2

ตัวดำเนินการ sizeof คือเอนทิตีเวลาคอมไพล์ไม่ใช่รันไทม์และไม่จำเป็นต้องมีวงเล็บเหมือนฟังก์ชัน เมื่อคอมไพล์โค้ดแล้วจะแทนที่ค่าด้วยขนาดของตัวแปรนั้นในเวลาคอมไพล์ แต่ในฟังก์ชันหลังจากที่ฟังก์ชันได้รับการดำเนินการแล้วเราจะทราบค่าที่ส่งคืน


1

เพราะ:

  • เมื่อคุณส่งค่าไปยังฟังก์ชันขนาดของวัตถุจะไม่ถูกส่งไปยังฟังก์ชันดังนั้นsizeof"ฟังก์ชัน" จะไม่มีทางกำหนดขนาดได้
  • ใน C ฟังก์ชันสามารถยอมรับอาร์กิวเมนต์ประเภทเดียวเท่านั้น sizeof () ต้องยอมรับสิ่งต่าง ๆ ทุกประเภท (ตัวแปรและประเภท! คุณไม่สามารถส่งผ่านประเภทไปยังฟังก์ชันใน C)
  • การเรียกใช้ฟังก์ชันเกี่ยวข้องกับการทำสำเนาอาร์กิวเมนต์และค่าใช้จ่ายที่ไม่จำเป็นอื่น ๆ

1

มีความแตกต่างเล็กน้อยจากฟังก์ชัน - ค่าของ sizeof ได้รับการแก้ไขในเวลาคอมไพล์ แต่ไม่ใช่ที่รันไทม์!


7
ยกเว้น VLA - อาร์เรย์ความยาวตัวแปร - อาร์กิวเมนต์
Jonathan Leffler

1

เนื่องจากเป็นตัวดำเนินการเวลาคอมไพล์ที่ในการคำนวณขนาดของออบเจ็กต์จำเป็นต้องใช้ข้อมูลประเภทที่พร้อมใช้งานในเวลาคอมไพล์เท่านั้น สิ่งนี้ไม่ถือสำหรับ C ++


0

sizeof()ตัวดำเนินการคือเวลาคอมไพล์จะเกิดขึ้น สามารถใช้เพื่อกำหนดพารามิเตอร์หรืออาร์กิวเมนต์


-1

Sizeof () ฉันคิดว่ามันเป็นทั้งฟังก์ชันและตัวดำเนินการ ทำไม? เนื่องจากฟังก์ชันมีวงเล็บสำหรับรายการที่ขั้นตอนการป้อนข้อมูล แต่ส่วนใหญ่แล้วตัวดำเนินการทำให้ตัวดำเนินการเป็นตัวดำเนินการดังนั้น sizeof จึงเป็นคำสั่งการดำเนินการที่ดำเนินการกับตัวถูกดำเนินการในวงเล็บ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.