การเริ่มต้นโครงสร้างเป็น 0


116

ถ้าฉันมีโครงสร้างแบบนี้:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

อะไรคือวิธีที่ง่ายที่สุดในการเริ่มต้นโครงสร้างนี้เป็น 0 ต่อไปนี้จะเพียงพอหรือไม่?

myStruct _m1 = {0};

หรือฉันจะต้องทำให้สมาชิกแต่ละคนเป็น 0 อย่างชัดเจน?

myStruct _m2 = {0,0};

คำตอบ:


143

ประการแรกคือการที่ง่ายที่สุด ( ที่เกี่ยวข้องกับการพิมพ์น้อย ) และมีการประกันเพื่อการทำงานที่สมาชิกทุกคนจะถูกตั้งค่า0[Ref 1]
อย่างที่สองคืออ่านได้มากขึ้น

ทางเลือกขึ้นอยู่กับความชอบของผู้ใช้หรือความต้องการมาตรฐานการเข้ารหัสของคุณ

[Ref 1] อ้างอิง C99 มาตรฐาน 6.7.8.21:

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

อ่านดี:
C และ C ++: การเริ่มต้นบางส่วนของโครงสร้างอัตโนมัติ


9
นอกจากนี้ฉันใช้= {};อย่างไรก็ตามฉันไม่แน่ใจว่าถูกต้องหรือไม่
William Entriken

15
@FullDecent วงเล็บว่างสำหรับการเริ่มต้นเป็นส่วนขยาย GNU
a3f

2
@ alias65536 คำถามถูกแท็ก C ไม่ใช่ C ++
a3f

3
ฉันได้รับข้อผิดพลาด: "ไม่มีวงเล็บปีกการอบตัวเริ่มต้น [-Werror = missing-braces]" อาจเป็นเพราะอาร์เรย์สมาชิก: /
DrumM

3
@Edenia ฉันไม่เห็นด้วย. ฉันรู้แล้วว่าfoo = {0}หมายถึงอะไร ถ้าฉันเห็นfoo = ZERO_FULLฉันต้อง grep สำหรับคำจำกัดความของ ZERO_FULL
Andrew Bainbridge

32

หากข้อมูลเป็นตัวแปรคงที่หรือทั่วโลกข้อมูลจะถูกเติมเป็นศูนย์ตามค่าเริ่มต้นดังนั้นเพียงแค่ประกาศ myStruct _m;

หากข้อมูลที่เป็นตัวแปรท้องถิ่นหรือโซนกองจัดสรรล้างมันด้วยmemsetเช่น:

memset(&m, 0, sizeof(myStruct));

คอมไพเลอร์ปัจจุบัน (เช่นเวอร์ชันล่าสุดgcc) เพิ่มประสิทธิภาพที่ค่อนข้างดีในทางปฏิบัติ สิ่งนี้ใช้ได้เฉพาะในกรณีที่ค่าศูนย์ทั้งหมด (รวมถึงพอยน์เตอร์ว่างและจุดศูนย์ลอยตัว) แสดงเป็นศูนย์บิตทั้งหมดซึ่งเป็นจริงในทุกแพลตฟอร์มที่ฉันรู้ (แต่มาตรฐานCอนุญาตให้ใช้งานในกรณีที่เป็นเท็จฉันไม่รู้ว่าไม่มีการนำไปใช้) .

คุณอาจจะเขียนโค้ดmyStruct m = {};หรือ myStruct m = {0};(แม้ว่าสมาชิกตัวแรกmyStructจะไม่ใช่สเกลาร์ก็ตาม)

ความรู้สึกของฉันคือการใช้memsetโครงสร้างโลคัลเป็นสิ่งที่ดีที่สุดและมันบ่งบอกถึงความจริงที่ว่าในรันไทม์ต้องทำบางอย่างได้ดีขึ้น (ในขณะที่โดยปกติข้อมูลส่วนกลางและข้อมูลคงที่สามารถเข้าใจได้ว่าเริ่มต้นในเวลาคอมไพล์โดยไม่มีค่าใช้จ่ายใด ๆ ในรันไทม์) .


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

1
คุณสามารถแบ่งปันตัวอย่าง Sander ได้หรือไม่? ความอยากรู้ของแท้ (เห็นได้ชัดว่าไม่ใช่ความจริงในระดับสากลไม่จำเป็นต้องหมายความว่ามีข้อยกเว้นที่อธิบายได้ง่าย แต่ถ้ามี ... )
Steven Fisher

2
Cมาตรฐานอนุญาตให้ชี้โมฆะ (หรือจำนวนจุดศูนย์ลอย) ที่จะเป็นตัวแทนในหน่วยความจำโดยสิ่งอื่นมากกว่าศูนย์ทั้งหมดบิต มีการใช้งานน้อยมากและแปลก ๆ (ฉันไม่สามารถตั้งชื่อได้)
Basile Starynkevitch

-1 คุณอาจพบการเริ่มต้นที่ OP ถามว่าน่าเกลียด แต่มันเป็นสิ่งที่ถูกมองข้ามโดยมาตรฐานและสามารถปรับให้เหมาะสมได้อย่างง่ายดายโดยคอมไพเลอร์ทั้งหมด จากนั้นแบบฟอร์ม{}ไม่ใช่ C ที่ถูกต้อง แต่ใช้ได้เฉพาะใน C ++
Jens Gustedt

7
@Steven: ฉันคิดได้แค่แพลตฟอร์มที่คลุมเครือและ / หรือเก่า ๆ ซีคำถามที่พบบ่อยมีรายชื่อของแพลตฟอร์มที่มีเป็นNULLตัวชี้ที่ไม่ได้ทั้งหมด0บิต: c-faq.com/null/machexamp.html จากนั้นมีความเป็นไปได้ที่แพลตฟอร์มไม่ได้ใช้ IEEE 754 เพื่อแสดงค่าทศนิยม แต่ใช้การแสดงอื่น ๆ ที่ไม่มีค่า0บิตทั้งหมด0.0- แต่ยอมรับว่าฉันรู้ว่าไม่มีแพลตฟอร์มดังกล่าว
Sander De Dycker

19

ดู§6.7.9การเริ่มต้น:

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

ใช่ทั้งคู่ทำงาน โปรดทราบว่าใน C99 สามารถใช้วิธีการเริ่มต้นใหม่ที่เรียกว่าการเริ่มต้นที่กำหนดได้เช่นกัน:

myStruct _m1 = {.c2 = 0, .c1 = 1};

สิ่งที่สะดุดตาที่สุดคือ C89 อยู่แล้ว: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (สำคัญสำหรับเป้าหมายการประมวลผลสัญญาณที่เฉพาะเจาะจง)
Tobias
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.