อาร์เรย์ที่ต่อเนื่องกัน

Aug 26 2020

ฉันอยากรู้เกี่ยวกับประโยคในมาตรฐาน 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;
}

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

คำตอบ

24 chux-ReinstateMonica Aug 26 2020 at 17:41

OP: ทำไมออบเจ็กต์ที่ตามหลังอาร์เรย์จึงต้องเป็นอาร์เรย์อื่น?

มันไม่ใช่. "... จุดเริ่มต้นของอาร์เรย์อื่น ... " เป็นการทำให้เข้าใจง่าย ข้อมูลจำเพาะต่อไปคือ:

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


OP: อาจเป็นวัตถุประเภทเดียวกับประเภทฐานอาร์เรย์ไม่ได้ (เช่นintต่อไปนี้ทันทีint[]) หรือไม่?

ใช่.

8 th33lf Aug 26 2020 at 17:26

ประการแรกการระบุอาร์เรย์ที่นี่ไม่ได้ยกเว้น / ห้ามวัตถุเดียว ออบเจ็กต์เดียวในหน่วยความจำแยกไม่ออกจากอาร์เรย์ขนาด 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;
}