อาร์เรย์ที่ต่อเนื่องกัน
ฉันอยากรู้เกี่ยวกับประโยคในมาตรฐาน C18:
พอยน์เตอร์สองตัวเปรียบเทียบค่าเท่ากันถ้าทั้งสองเป็นพอยน์เตอร์ว่างทั้งสองเป็นพอยน์เตอร์ไปยังอ็อบเจ็กต์เดียวกัน (รวมถึงพอยน์เตอร์ไปยังอ็อบเจ็กต์และอ็อบเจ็กต์ย่อยที่จุดเริ่มต้น) หรือฟังก์ชันทั้งสองตัวชี้ไปยังหนึ่งในองค์ประกอบสุดท้ายของอาร์เรย์เดียวกัน ออบเจ็กต์หรือตัวหนึ่งเป็นตัวชี้ไปยังจุดสิ้นสุดของออบเจ็กต์อาร์เรย์หนึ่งและอีกตัวเป็นตัวชี้ไปยังจุดเริ่มต้นของออบเจ็กต์อาร์เรย์อื่นที่เกิดขึ้นตามวัตถุอาร์เรย์แรกในพื้นที่แอดเดรส § 6.5.9 6
เหตุใดออบเจ็กต์ที่ตามหลังอาร์เรย์จึงจำเป็นต้องเป็นอาร์เรย์อื่น ไม่สามารถเป็นวัตถุประเภทเดียวกับประเภทฐานอาร์เรย์ได้ (เช่นintต่อไปนี้ทันทีint[]) หรือไม่?
ไม่น่าแปลกใจที่ฉันได้ลองใช้รหัสนี้:
#include <stdio.h>
struct test { int arr[10]; int i; };
int main() {
struct test t;
int *p, *q;
p = t.arr + 10;
q = &t.i;
if (p == q)
printf("Equal pointers.");
return 0;
}
และให้พอยน์เตอร์เท่ากัน พฤติกรรมนี้ไม่สามารถรับประกันได้เลยว่าเป็นเพียงความบังเอิญที่กำหนดโดยการนำไปใช้จริงหรือไม่?
คำตอบ
OP: ทำไมออบเจ็กต์ที่ตามหลังอาร์เรย์จึงต้องเป็นอาร์เรย์อื่น?
มันไม่ใช่. "... จุดเริ่มต้นของอาร์เรย์อื่น ... " เป็นการทำให้เข้าใจง่าย ข้อมูลจำเพาะต่อไปคือ:
สำหรับวัตถุประสงค์ของตัวดำเนินการเหล่านี้ตัวชี้ไปยังวัตถุที่ไม่ใช่องค์ประกอบของอาร์เรย์จะทำงานเหมือนกับตัวชี้ไปยังองค์ประกอบแรกของอาร์เรย์ที่มีความยาวหนึ่งโดยมีชนิดของวัตถุเป็นประเภทองค์ประกอบ C17dr § 6.5.9 7
OP: อาจเป็นวัตถุประเภทเดียวกับประเภทฐานอาร์เรย์ไม่ได้ (เช่น
intต่อไปนี้ทันทีint[]) หรือไม่?
ใช่.
ประการแรกการระบุอาร์เรย์ที่นี่ไม่ได้ยกเว้น / ห้ามวัตถุเดียว ออบเจ็กต์เดียวในหน่วยความจำแยกไม่ออกจากอาร์เรย์ขนาด 1
( แก้ไข : อ่านคำตอบนี้สำหรับการอ้างอิงจากมาตรฐานที่ระบุไว้อย่างชัดเจนเมื่ออ้างถึงพอยน์เตอร์)
ประการที่สองมาตรฐานยังพยายามชี้แจงคำแถลงที่คุณยกมาด้วยเชิงอรรถต่อไปนี้ระบุสถานการณ์ที่ใช้กฎ:
วัตถุสองชิ้นสามารถอยู่ติดกันในหน่วยความจำได้เนื่องจากเป็นองค์ประกอบที่อยู่ติดกันของอาร์เรย์ขนาดใหญ่หรือสมาชิกที่อยู่ติดกันของโครงสร้างโดยไม่มีช่องว่างระหว่างกันหรือเนื่องจากการนำไปใช้งานเลือกที่จะวางไว้เช่นนั้นแม้ว่าจะไม่เกี่ยวข้องกันก็ตาม
เมื่อรวมทุกอย่างเข้าด้วยกันสิ่งที่มาตรฐานพยายามจะพูดในที่นี้ก็คือโดยทั่วไปแล้วตัวชี้สองตัวสำหรับวัตถุที่แตกต่างกันไม่ควรเปรียบเทียบเท่ากัน อย่างไรก็ตามเนื่องจากเป็นเรื่องถูกกฎหมายที่จะชี้ไปที่หนึ่งนอกเหนือจากวัตถุอาร์เรย์ในหน่วยความจำหากมีวัตถุ (อาร์เรย์) อื่นที่ตำแหน่งนั้นก็ยังคงถูกกฎหมายสำหรับตัวชี้ที่จะเปรียบเทียบเท่ากับตัวชี้กับวัตถุที่อยู่ติดกัน ตอนนี้อาจมีหรือไม่มีวัตถุที่ถูกต้องในตำแหน่งนี้เนื่องจากตัวเลือกการจัดตำแหน่งและช่องว่างภายใน แต่ถ้ามีก็เป็นที่ยอมรับสำหรับตัวชี้เหล่านี้ในการเปรียบเทียบค่าเท่ากัน
ในตัวอย่างของคุณถ้าฉันเปลี่ยนอาร์เรย์เป็นถ่านพอยน์เตอร์อาจจะเปรียบเทียบไม่เท่ากันเนื่องจากคอมไพเลอร์เลือกที่จะจัดแนว int เป็น 4 ไบต์ (บนแพลตฟอร์ม 32 หรือ 64 บิตส่วนใหญ่) จึงแนะนำช่องว่างภายใน พฤติกรรมนี้ยังคงถูกกฎหมายตามมาตรฐาน
#include <stdio.h>
struct test { char arr[10]; int i; };
int main() {
struct test t;
int *p, *q;
p = (int*)(t.arr + 10);
q = &t.i;
if(p == q)
printf("Equal pointers.");
else
printf("Unequal pointers.");
return 0;
}