ฉันใช้รหัสต่อไปนี้ผ่านคอมไพเลอร์ต่าง ๆ :
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 รหัสจะรวบรวมโดยไม่มีคำเตือน
void**
ไม่ใช่ตัวชี้ทั่วไป อย่างเดียวvoid*
คือ
(void**)
เป็นตัวละครสไตล์ c ชัดเจน มันบอกคอมไพเลอร์ว่าอย่ามองสิ่งที่คุณทำอย่างใกล้ชิดและเชื่อใจคุณ มันเป็นการแทนที่อย่างชัดเจนของระบบความปลอดภัยประเภทและคอมไพเลอร์จำเป็นต้องยอมรับการแปลงใด ๆ สไตล์ C ควรหลีกเลี่ยงมันมีพลังมากเกินไป ใช้ภาษา C ++ static_cast
ซึ่งจะบ่นถ้าคุณพยายามทำสิ่งที่ไม่สมเหตุสมผล