&& หมายถึงอะไรในโมฆะ * p = && abc;


102

void *p = &&abc;ฉันมาข้ามชิ้นส่วนของรหัส ความสำคัญของ&&ที่นี่คืออะไร? ฉันรู้เกี่ยวกับการอ้างอิง rvalue แต่ฉันคิดว่า&&ใช้ในบริบทนี้แตกต่างกัน อะไร&&บ่งชี้ในvoid *p = &&abc;?


14
คุณเห็นสิ่งนี้ที่ไหน
user541686

3
ฉันอยากรู้ด้วยว่าคุณเคยเห็นสิ่งนี้ที่ไหน
Flavius

คำตอบ:


154

&&เป็นส่วนขยายของ gccเพื่อรับที่อยู่ของป้ายกำกับที่กำหนดไว้ในฟังก์ชันปัจจุบัน

void *p = &&abc ผิดกฎหมาย C99 และ C ++ มาตรฐาน

ซึ่งรวบรวมด้วย g ++


42
ลองนึกภาพว่าโปรแกรมเมอร์ทุกคนจะดีขึ้นแค่ไหนถ้า gcc มี -pedantic โดยค่าเริ่มต้น จากนั้นผู้คนจะเรียนรู้ C แทนข้อมูลที่ไม่เกี่ยวข้องเกี่ยวกับ gnus
Lundin

4
แฮ็คอะไร void*หากพวกเขาคิดค้นไวยากรณ์ใหม่สำหรับตัวชี้ฉลากพวกเขาควรจะคิดค้นรูปแบบใหม่สำหรับมันเช่นเดียวแทนการใช้
Mark Ransom

1
@Prasoon Saurav: ใครก็ตามที่ลดลงอาจจะไม่เห็นด้วยกับคุณลักษณะนี้และจะนำออกมาให้คุณ
Chuck

@Lundin: คอมไพเลอร์ส่วนใหญ่สามารถพูดได้เหมือนกัน __forceinlineเหรอ? __declspec(naked)เหรอ? MSVCisms หนึ่งที่ฉันชอบคือ: template<typename T> class X { friend T; }ซึ่งไม่ถูกต้อง C ++ 03
Sebastian Mach

ลิงค์ที่สองตายแล้ว
Cœur

96

จะหาได้อย่างไร

นั่นเป็นอยู่ของฉลากและมันเป็นเฉพาะคุณสมบัติในการGCC

int main(void) {
    void* startp;
s:
    startp = &&s;
    printf("the assignment above starts at address %p\n", startp);
    return 0;
}

คุณสามารถหาได้ด้วยตัวเองโดยการทดสอบ:

int main(void) {
    void* startp;
    int a;
    startp = &&a;
    printf("startp=%p\n", startp);
    return 0;
}

ในกรณีนี้ GCC กล่าวว่า:

ข้อผิดพลาด: ใช้ป้ายกำกับ 'a' แต่ไม่ได้กำหนด

ใต้ฝากระโปรง - การประกอบ

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

หลังจากระบบปฏิบัติการโหลดไฟล์. exe จากดิสก์ส่วนประกอบของระบบปฏิบัติการที่เรียกว่า "ตัวโหลด" (windows มี "PE Loader", linux มี "ELF loader" หรืออาจจะเป็นไฟล์อื่น ๆ หากคอมไพล์อยู่ใน เคอร์เนล) ทำ "เวอร์ชวลไลเซชัน" ของโปรแกรมนั้นโดยเปลี่ยนเป็นกระบวนการ

กระบวนการนี้คิดว่าเป็นเพียงหน่วยเดียวใน RAM และสามารถเข้าถึง RAM ทั้งหมดได้ (นั่นคือ 0x00000000-0xFFFFFFFF บนเครื่อง 32 บิต)

(ข้างต้นเป็นเพียงมุมมองสั้น ๆ ของสิ่งที่เกิดขึ้นคุณต้องเรียนรู้การประกอบเพื่อให้เข้าใจอย่างถ่องแท้ดังนั้นอดทนกับฉัน)

ตอนนี้ป้ายกำกับในซอร์สโค้ดนั้นโดยพื้นฐานแล้วคือที่อยู่ "ป้าย goto;" ไม่ทำอะไรอื่นนอกจากการข้ามไปยังที่อยู่นั้น (ลองนึกถึงตัวชี้คำสั่งในชุดประกอบ) ป้ายนี้เก็บที่อยู่ RAM นี้และนั่นคือวิธีที่คุณสามารถค้นหาที่อยู่นั้นได้

หลังจากที่คุณได้เรียนรู้ ASM แล้วคุณจะรู้ว่าที่อยู่นั้นชี้ไปที่คำสั่งภายใน.textส่วนของไฟล์ปฏิบัติการ .textส่วนคือหนึ่งซึ่งถือ (binary) คุณโปรแกรมรหัสที่จะดำเนินการ

คุณสามารถตรวจสอบสิ่งนี้ได้ด้วย:

objdump -x a.out

ตัวอย่างที่ใช้ได้จริง

ตามที่อธิบายไว้ในGCCคุณสามารถใช้เพื่อเริ่มต้นตารางกระโดด เครื่องกำเนิดสแกนเนอร์บางรุ่นเช่นre2c (ดู-gพารามิเตอร์) ใช้เพื่อสร้างเครื่องสแกนที่มีขนาดกะทัดรัดมากขึ้น บางทีอาจมีตัวสร้างพาร์เซอร์ที่ใช้เทคนิคเดียวกัน


4
คอมไพล์ด้วย -std = c99 -pedantic
Lundin

2
ค่อนข้างสำคัญที่จะต้องพูดถึงว่าเป็นส่วนขยาย GCC ไม่ใช่ส่วนหลักของภาษา
ม.ค.

1
นั่นคือ Flavius ​​ที่น่าประทับใจทีเดียว
Octavian A. Damiean

1
ฉันชอบคำตอบแบบนี้ผู้คนจำนวนมากต้องได้รับการสอนวิธีค้นหาคำตอบแทนที่จะเพียงแค่บอก
Letseatlunch

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