การแปลงเป็นโมฆะ ** บนคอมไพเลอร์ต่างกัน


9

ฉันใช้รหัสต่อไปนี้ผ่านคอมไพเลอร์ต่าง ๆ :

int main()
{
    float **a;
    void **b;
    b = a;
}

จากสิ่งที่ฉันได้รับสามารถที่จะรวบรวมvoid **เป็นไม่ได้เป็นตัวชี้ทั่วไปซึ่งหมายความว่าการแปลงใด ๆ จากตัวชี้อีกไม่ควรรวบรวมหรืออย่างน้อยโยนเตือน อย่างไรก็ตามนี่คือผลลัพธ์ของฉัน (ทำบน Windows):

  • gcc - ส่งคำเตือนตามที่คาดไว้
  • g ++ - โยนข้อผิดพลาดตามที่คาดไว้ (นี่เป็นเพราะการพิมพ์ที่อนุญาตน้อยกว่าของ C ++ ใช่ไหม?)
  • MSVC (cl.exe) - ไม่มีการเตือนใด ๆ แม้จะมีการระบุ / Wall

คำถามของฉันคือ: ฉันขาดอะไรบางอย่างเกี่ยวกับสิ่งทั้งปวงและมีเหตุผลเฉพาะที่ทำให้ MSVC ไม่สร้างคำเตือนหรือไม่? MSVC ไม่ผลิตเตือนเมื่อมีการแปลงจาก ไปvoid **float **

สิ่งที่ควรทราบอีกประการหนึ่ง: หากฉันแทนที่a = bด้วยการแปลงที่ชัดเจนa = (void **)bไม่มีคอมไพเลอร์คนใดโยนคำเตือน ฉันคิดว่านี่น่าจะเป็นตัวละครที่ไม่ถูกต้องดังนั้นทำไมไม่มีคำเตือน?

เหตุผลที่ฉันถามคำถามนี้ก็เพราะฉันเริ่มเรียนรู้ CUDA และในคู่มือการเขียนโปรแกรมอย่างเป็นทางการ ( https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-memory ) รหัสต่อไปนี้สามารถพบได้:

// Allocate vectors in device memory
float* d_A;
cudaMalloc(&d_A, size);

ซึ่งควรดำเนินการแปลงนัยเพื่อvoid **สำหรับ&d_Aเป็นอาร์กิวเมนต์แรกของการเป็นประเภทcudaMalloc void **รหัสที่คล้ายกันสามารถพบได้ทั่วเอกสาร นี่เป็นเพียงการทำงานเลอะเทอะในตอนท้ายของ NVIDIA หรือฉันหรือเปล่า ตั้งแต่nvccใช้ MSVC รหัสจะรวบรวมโดยไม่มีคำเตือน


3
ข้อผิดพลาดจากการโพสต์ 3 รายการสด: godbolt.org/z/GQWMNo
Richard Critten

3
รหัสข้อผิดพลาดสำหรับฉันด้วย MSVC คุณใช้เวอร์ชั่นไหน แต่ใช่void**ไม่ใช่ตัวชี้ทั่วไป อย่างเดียวvoid*คือ
NathanOliver

ขอบคุณสำหรับคำตอบด่วน! เห็นได้ชัดว่า 19.24.28315 สำหรับ x64? ฉันไม่เคยใช้ MSVC มาก่อน
CaptainProton42

2
(void**)เป็นตัวละครสไตล์ c ชัดเจน มันบอกคอมไพเลอร์ว่าอย่ามองสิ่งที่คุณทำอย่างใกล้ชิดและเชื่อใจคุณ มันเป็นการแทนที่อย่างชัดเจนของระบบความปลอดภัยประเภทและคอมไพเลอร์จำเป็นต้องยอมรับการแปลงใด ๆ สไตล์ C ควรหลีกเลี่ยงมันมีพลังมากเกินไป ใช้ภาษา C ++ static_castซึ่งจะบ่นถ้าคุณพยายามทำสิ่งที่ไม่สมเหตุสมผล
François Andrieux

@RichardCritten ภาษาที่ไม่ถูกต้อง - ไม่มีข้อผิดพลาดgodbolt.org/z/RmFpgN C ++ cuda ต้องการการปลดเปลื้องที่ชัดเจนเช่นเคย
P__J__

คำตอบ:


4

ฉันขาดอะไรบางอย่างเกี่ยวกับสิ่งทั้งปวงและมีเหตุผลเฉพาะที่ว่าทำไม MSVC ไม่สร้างคำเตือน? MSVC สร้างคำเตือนเมื่อแปลงจากโมฆะเป็นลอย **

การมอบหมายนี้โดยไม่ใช้นักแสดงเป็นการละเมิดข้อ จำกัด ดังนั้นคอมไพเลอร์ที่ได้มาตรฐานจะพิมพ์คำเตือนหรือข้อผิดพลาด อย่างไรก็ตาม MSVC ไม่สอดคล้องกับการปรับใช้ C อย่างสมบูรณ์

สิ่งที่ควรทราบอีกประการหนึ่ง: ถ้าฉันแทนที่ a = b ด้วยการแปลงที่ชัดเจน a = (void **) b ไม่มีคอมไพเลอร์ตัวใดที่ส่งคำเตือน ฉันคิดว่านี่น่าจะเป็นตัวละครที่ไม่ถูกต้องดังนั้นทำไมไม่มีคำเตือน?

อนุญาตให้มีการแปลงตัวชี้โดยการส่งในตัวนักแสดงในบางสถานการณ์ มาตรฐาน C ระบุสิ่งต่อไปนี้ในหัวข้อ 6.3.2.3p7:

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

ดังนั้นคุณสามารถแปลงระหว่างประเภทของตัวชี้หากไม่มีปัญหาการจัดตำแหน่งและคุณแปลงกลับได้เท่านั้น (เว้นแต่เป้าหมายจะเป็นchar *)

float* d_A;
cudaMalloc(&d_A, size);

...

นี่เป็นเพียงการทำงานเลอะเทอะในตอนท้ายของ NVIDIA หรือฉันอีกครั้งหายไปบางสิ่งบางอย่าง?

สันนิษฐานว่าฟังก์ชั่นนี้กำลังยกเลิกการลงทะเบียนตัวชี้และเขียนที่อยู่ของหน่วยความจำที่จัดสรรไว้ นั่นก็หมายความว่ามันเป็นความพยายามที่จะเขียนไปราวกับว่ามันเป็นfloat * void *นี้ไม่ได้เป็นเช่นเดียวกับแปลงทั่วไป / void *จาก การพูดอย่างนี้ดูเหมือนว่าพฤติกรรมที่ไม่ได้กำหนดแม้ว่ามันจะ "ได้ผล" เพราะโปรเซสเซอร์ x86 ที่ทันสมัย ​​(เมื่อไม่ได้อยู่ในโหมดจริง) ใช้การแทนค่าเดียวกันสำหรับตัวชี้ทุกประเภท


@ dbush ข้อมูลมากขอบคุณ! ฉันเข้าใจว่าทำไมมันถึงได้ผลถ้ามันใช้งานได้ ยังคงคอมไพเลอร์ส่วนใหญ่จะไม่ส่งคำเตือนหรือข้อผิดพลาดเพราะ&d_Aไม่มีประเภทที่จำเป็น?
CaptainProton42

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