ไม่ใช่พฤติกรรมที่ไม่ได้กำหนดไม่ว่าใครก็ตามจะพูดอย่างเป็นทางการหรืออย่างอื่นก็ตามเพราะมันถูกกำหนดโดยมาตรฐาน p->s
ยกเว้นเมื่อใช้เป็น lvalue, (char *)p + offsetof(struct T, s)
ประเมินตัวชี้ไปเหมือนกัน โดยเฉพาะอย่างยิ่งนี่คือchar
ตัวชี้ที่ถูกต้องภายในอ็อบเจ็กต์ malloc'd และมี 100 (หรือมากกว่านั้นขึ้นอยู่กับการพิจารณาการจัดตำแหน่ง) ที่อยู่ต่อเนื่องตามหลังมันซึ่งใช้ได้เช่นกันเป็นchar
อ็อบเจ็กต์ภายในอ็อบเจ็กต์ที่จัดสรร ความจริงที่ว่าพอยน์เตอร์ได้มาจากการใช้->
แทนการเพิ่มออฟเซ็ตให้กับตัวชี้ที่ส่งกลับโดยmalloc
โยนไปอย่างชัดเจนchar *
นั้นไม่เกี่ยวข้อง
ในทางเทคนิคp->s[0]
เป็นองค์ประกอบเดียวของchar
อาร์เรย์ภายในโครงสร้างองค์ประกอบสองสามรายการถัดไป (เช่นp->s[1]
ผ่านp->s[3]
) มีแนวโน้มที่จะเพิ่มไบต์ภายในโครงสร้างซึ่งอาจเสียหายได้หากคุณทำการกำหนดให้กับโครงสร้างโดยรวม แต่ไม่ใช่ถ้าคุณเพียงแค่เข้าถึงแต่ละรายการ สมาชิกและองค์ประกอบที่เหลือคือพื้นที่เพิ่มเติมในออบเจ็กต์ที่จัดสรรซึ่งคุณมีอิสระที่จะใช้ตามที่คุณต้องการตราบใดที่คุณปฏิบัติตามข้อกำหนดการจัดตำแหน่ง (และchar
ไม่มีข้อกำหนดในการจัดตำแหน่ง)
หากคุณกังวลว่าความเป็นไปได้ของการทับซ้อนกับไบต์ช่องว่างในโครงสร้างอาจทำให้เกิดปีศาจจมูกได้คุณสามารถหลีกเลี่ยงสิ่งนี้ได้โดยการแทนที่1
อิน[1]
ด้วยค่าที่ทำให้แน่ใจว่าไม่มีช่องว่างที่ส่วนท้ายของโครงสร้าง วิธีง่ายๆ แต่สิ้นเปลืองในการทำเช่นนี้คือการสร้างโครงสร้างที่มีสมาชิกที่เหมือนกันยกเว้นไม่มีอาร์เรย์ต่อท้ายและใช้s[sizeof struct that_other_struct];
สำหรับอาร์เรย์ จากนั้นp->s[i]
มีการกำหนดไว้อย่างชัดเจนเป็นองค์ประกอบของอาร์เรย์ที่ struct สำหรับi<sizeof struct that_other_struct
และเป็นวัตถุถ่านที่อยู่ต่อไปนี้ในตอนท้ายของ struct i>=sizeof struct that_other_struct
สำหรับ
แก้ไข:จริงๆแล้วในเคล็ดลับข้างต้นเพื่อให้ได้ขนาดที่เหมาะสมคุณอาจต้องใส่ยูเนี่ยนที่มีทุกประเภทก่อนอาร์เรย์เพื่อให้แน่ใจว่าอาร์เรย์นั้นเริ่มต้นด้วยการจัดตำแหน่งสูงสุดแทนที่จะอยู่ตรงกลางของช่องว่างภายในขององค์ประกอบอื่น ๆ . อีกครั้งฉันไม่เชื่อว่าสิ่งเหล่านี้เป็นสิ่งจำเป็น แต่ฉันเสนอสิ่งนี้สำหรับนักกฎหมายภาษาที่หวาดระแวงที่สุด
แก้ไข 2:การทับซ้อนกับไบต์ของช่องว่างภายในไม่ใช่ปัญหาอย่างแน่นอนเนื่องจากส่วนอื่นของมาตรฐาน C กำหนดให้ถ้าโครงสร้างสองอย่างเห็นพ้องกันในการเริ่มต้นขององค์ประกอบต่อมาองค์ประกอบเริ่มต้นทั่วไปสามารถเข้าถึงได้ผ่านทางตัวชี้ไปยังประเภทใดประเภทหนึ่ง ดังนั้นหากมีการประกาศโครงสร้างที่เหมือนกันstruct T
แต่มีอาร์เรย์สุดท้ายที่ใหญ่กว่าองค์ประกอบs[0]
จะต้องตรงกับองค์ประกอบs[0]
ในstruct T
และการมีอยู่ขององค์ประกอบเพิ่มเติมเหล่านี้ไม่สามารถส่งผลกระทบหรือได้รับผลกระทบจากการเข้าถึงองค์ประกอบทั่วไปของโครงสร้างที่ใหญ่กว่า struct T
โดยใช้ตัวชี้ไปยัง