array [100] = {0} ตั้งค่า array ทั้งหมดเป็น 0 อย่างไร


140

คอมไพเลอร์กรอกค่าchar array[100] = {0};อย่างไร เวทย์มนตร์ที่อยู่เบื้องหลังมันคืออะไร?

ฉันอยากรู้ว่าคอมไพเลอร์เริ่มต้นอย่างไร


1
ใน C หรือ C ++ พวกเขาเป็นสองคำถามแยกกัน
Toby Speight

คำตอบ:


163

มันไม่ใช่เวทมนตร์

พฤติกรรมของรหัสนี้ใน C อธิบายไว้ในส่วนที่ 6.7.8.21 ของข้อมูลจำเพาะ C ( แบบร่างออนไลน์ของข้อมูลจำเพาะ C ): สำหรับองค์ประกอบที่ไม่มีค่าที่ระบุคอมไพเลอร์จะเริ่มต้นตัวชี้เป็น NULL และประเภทคณิตศาสตร์เป็นศูนย์ ( และนำสิ่งนี้ไปใช้ซ้ำกับการรวมซ้ำ)

พฤติกรรมของรหัสนี้ใน C ++ อธิบายไว้ในส่วนที่ 8.5.1.7 ของข้อกำหนด C ++ ( แบบร่างออนไลน์ของข้อมูลจำเพาะ C ++ ): คอมไพเลอร์สรุปรวม - เริ่มต้นองค์ประกอบที่ไม่มีค่าที่ระบุ

นอกจากนี้โปรดทราบว่าใน C ++ (แต่ไม่ใช่ C) คุณสามารถใช้รายการ initializer ว่างได้ทำให้คอมไพเลอร์รวมการเริ่มต้นองค์ประกอบทั้งหมดของอาร์เรย์:

char array[100] = {};

สำหรับโค้ดประเภทใดที่คอมไพเลอร์อาจสร้างขึ้นเมื่อคุณทำสิ่งนี้ให้ดูที่คำถามนี้: แอสเซมบลีที่แปลกจากอาร์เรย์ 0-initialization


คอมไพเลอร์ C ทั้งหมดทำสิ่งนี้หรือไม่? ฉันเชื่อว่า Visual Studio ทำสิ่งนี้เท่านั้น
JFA

1
ร่างออนไลน์ของรายละเอียด c ++ เสียแล้วใครมีลิงค์ใหม่บ้าง
Behrooz Karjoo

35

การใช้งานขึ้นอยู่กับนักพัฒนาคอมไพเลอร์

หากคำถามของคุณคือ "สิ่งที่จะเกิดขึ้นกับการประกาศดังกล่าว" - คอมไพเลอร์จะตั้งค่าองค์ประกอบอาร์เรย์แรกเป็นค่าที่คุณระบุ (0) และอื่น ๆ ทั้งหมดจะถูกตั้งค่าเป็นศูนย์เพราะเป็นค่าเริ่มต้นสำหรับองค์ประกอบอาร์เรย์ที่ละเว้น


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

10
Ryan ถ้าคุณไม่ได้ตั้งค่าสำหรับองค์ประกอบแรกที่ทั้งอาร์เรย์นั้นไม่ได้กำหนดค่าเริ่มต้นและมีขยะจริง ๆ แต่ถ้าคุณตั้งค่าอย่างน้อยหนึ่งองค์ประกอบของมันอาร์เรย์ทั้งหมดจะกลายเป็นค่าเริ่มต้นเพื่อให้องค์ประกอบที่ไม่ได้รับค่าเริ่มต้น 0.
qrdl

1
สำหรับ C ++ รายการ initializer ว่างสำหรับอาร์เรย์ที่มีขอบเขตจะกำหนดค่าเริ่มต้นให้กับองค์ประกอบทั้งหมด
dalle

2
@NatanYellin ฉันพูดว่านี่ไม่ได้กำหนดไว้ที่ไหน? โปรดอ่านคำตอบแบบเต็มก่อนที่จะแสดงความคิดเห็นและ downvoting
qrdl

1
@qrdl คุณพูดถูก ฉันเข้าใจความคิดเห็นของคุณเกี่ยวกับการใช้งานผิด น่าเสียดายที่ฉันไม่สามารถเปลี่ยนการลงคะแนนของฉันได้ในตอนนี้
Natan Yellin

27

หากคอมไพเลอร์ของคุณคือ GCC คุณสามารถใช้ไวยากรณ์ต่อไปนี้:

int array[256] = {[0 ... 255] = 0};

โปรดดูที่ http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html#Designated-Initsและโปรดทราบว่านี่เป็นคุณลักษณะเฉพาะของคอมไพเลอร์


ยินดีต้อนรับ! ตั้งแต่คุณขอให้มองทุกประเภทดังกล่าวมากขึ้นของเทคนิคที่ผมได้ให้
lakshmanaraj

1
คุณสามารถทำสิ่งนี้ได้อย่างแน่นอนถ้าคุณเลือก แต่มีข้อเสียที่ชัดเจนในการพึ่งพาส่วนขยายเฉพาะคอมไพเลอร์เช่นนี้
Dan Olson

@Dan Olson คำถามของเขาตัวเองถามเกี่ยวกับคอมไพเลอร์เฉพาะและด้วยเหตุนี้โพสต์นี้ หากคุณรู้สึกว่ามันไร้ประโยชน์ฉันจะลบ
lakshmanaraj

5
มันไม่ไร้ประโยชน์มันน่าสนใจ ข้อแม้นั้นสมควรที่จะถูกบันทึกไว้
Dan Olson

2
สิ่งที่มันเช่นนี้ทำให้ฉันกลับมาที่ SO และการอ่านมากกว่าคำตอบไม่กี่ด้านบน ...
timday

19

ขึ้นอยู่กับตำแหน่งที่คุณวางการเริ่มต้นนี้

ถ้าอาร์เรย์คงที่เช่นเดียวกับใน

char array[100] = {0};

int main(void)
{
...
}

ดังนั้นจึงเป็นคอมไพเลอร์ที่สำรอง 100 0 ไบต์ใน data segement ของโปรแกรม ในกรณีนี้คุณอาจละเว้นผู้เริ่มต้น

หากอาร์เรย์ของคุณเป็นแบบอัตโนมัติแสดงว่าเป็นอีกเรื่องหนึ่ง

int foo(void)
{
char array[100] = {0};
...
}

ในกรณีนี้ทุกฟังก์ชั่นการโทร foo คุณจะมี memset ที่ซ่อนอยู่

รหัสข้างต้นเทียบเท่ากับ

int foo(void)
{ 
char array[100];

memset(array, 0, sizeof(array));
....
}

และถ้าคุณไม่ใช้ initializer อาร์เรย์ของคุณจะมีข้อมูลแบบสุ่ม (ข้อมูลของสแต็ก)

หากอาร์เรย์ในเครื่องของคุณถูกประกาศคงที่เช่นเดียวกับใน

int foo(void)
{ 
static char array[100] = {0};
...
}

ในทางเทคนิคแล้วมันเป็นกรณีเดียวกับกรณีแรก

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