Farklı derleyicilerde boşluğa ** dönüştürme


9

Farklı derleyiciler aracılığıyla aşağıdaki kodu çalıştırıyorum:

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

Ben toplamak mümkün kadarıyla, void **bir değil başka pointer herhangi dönüşüm derlemek ya da en azından bir uyarı atmak gerektiğini araçlarının genel bir işaretçi. Ancak, işte benim sonuçlarım (tümü Windows üzerinde yapılır):

  • gcc - Beklendiği gibi bir uyarı atar.
  • g ++ - Beklendiği gibi bir hata atar (bunun nedeni C ++ 'ın daha az izin veren yazımıdır, değil mi?)
  • MSVC (cl.exe) - / Wall belirtilse bile hiçbir uyarı alamaz.

Sorum şu: Her şey hakkında bir şey eksik mi ve MSVC'nin bir uyarı vermemesinin belirli bir nedeni var mı? Msvc yapar dönüştürürken bir uyarı üretmek arasından void ** için float **.

Başka bir şey: a = bAçık dönüşümle değiştirirsem a = (void **)b, derleyicilerin hiçbiri uyarı vermez. Bunun geçersiz bir oyuncu olması gerektiğini düşündüm, bu yüzden neden bir uyarı olmaz?

Bu soruyu sormamın nedeni, CUDA öğrenmeye başlamam ve resmi Programlama Kılavuzunda ( https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-memory ) aşağıdaki kod bulunabilir:

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

ilk argümanı tür olduğundan, void **for için örtük bir dönüşüm gerçekleştirmelidir . Benzer kod belgelerin her yerinde bulunabilir. Bu NVIDIA'nın sonundaki özensiz bir iş mi yoksa yine bir şey mi kaçırıyorum? Yana kullanır MSVC, kod uyarıları olmadan derler.&d_AcudaMallocvoid **nvcc


3
Gönderilen 3 canlı hata: godbolt.org/z/GQWMNo
Richard Critten

3
MSVC ile kod hataları benim için. Hangi sürümü kullanıyorsunuz? Ama evet, void**genel bir işaretçi değil. Sadece void*.
NathanOliver

Hızlı cevap için teşekkürler! Görünüşe göre x64 için 19.24.28315? Daha önce gerçekten MSVC kullanmadım.
CaptainProton42

2
(void**)açık bir c tarzı oyuncu. Derleyiciye ne yaptığınıza yakından bakmamasını ve size güvenmesini söyler. Tip güvenlik sisteminin açık bir şekilde geçersiz kılınması ve derleyicilerin temelde her türlü dönüşümü kabul etmesi gerekir. C tarzı atmalardan kaçınılmalıdır, çok güçlüdürler. static_castMantıklı olmayan bir şey yapmaya çalışıyorsanız şikayet edecek gibi C ++ dökümleri kullanın .
François Andrieux

@RichardYanlış dil - hata yok godbolt.org/z/RmFpgN C ++ cuda , genellikle olduğu gibi açık dökümler gerektirir.
P__J__

Yanıtlar:


4

Her şey hakkında bir şey mi eksik ve MSVC'nin uyarı vermemesinin belirli bir nedeni var mı? MSVC, boşluktan yüzdürme ** işlemine geçerken uyarı verir

Oyunculuğu olmayan bu atama bir kısıtlama ihlalidir, bu nedenle standart uyumlu bir derleyici bir uyarı veya hata yazdıracaktır. Ancak MSVC, C uygulamasıyla tam olarak uyumlu değildir.

Başka bir şey: a = b yerine a = (void **) b açık dönüşümünü koyarsam, derleyicilerin hiçbiri uyarı vermez. Bunun geçersiz bir oyuncu olması gerektiğini düşündüm, bu yüzden neden bir uyarı olmaz?

Bazı durumlarda oyuncu kadrosu aracılığıyla işaretçi dönüşümlerine izin verilir. C standardı bölüm 6.3.2.3p7'de şunları söylüyor:

Bir nesne türüne işaretçi farklı bir nesne türüne işaretçi olarak dönüştürülebilir. Ortaya çıkan işaretçi başvurulan tür için doğru şekilde hizalanmamışsa, davranış tanımsızdır. Aksi takdirde, tekrar dönüştürüldüğünde, sonuç orijinal işaretçiye eşittir. Nesneye yönelik bir işaretçi bir işaretçi türüne dönüştürüldüğünde, sonuç nesnenin adreslenen en düşük baytını gösterir. Sonucun art arda artması, nesnenin boyutuna kadar, nesnenin kalan baytlarına işaretçiler verir.

Bu nedenle , hizalama sorunu olmaması ve yalnızca geri dönüş yapmanız koşuluyla işaretçi türleri arasında dönüştürme yapabilirsiniz (hedef a değilse char *).

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

...

Bu NVIDIA'nın sonundaki özensiz bir iş mi yoksa yine bir şey mi kaçırıyorum?

Muhtemelen, bu işlev verilen işaretçiyi kaydırarak ayırır ve tahsis edilen belleğin adresini yazar. Bu demek oluyor ki, float *sanki a void *. Bu, a'ya /'den tipik dönüşümle aynı değildir void *. Modern x86 işlemcileri (gerçek modda değilken) tüm işaretçi türleri için aynı temsili kullandığından, bu kesinlikle tanımlanmamış davranışa benziyor.


@dbush Çok bilgilendirici, teşekkürler! Çalışıyorsa neden çalıştığını anladım. Yine de, çoğu derleyici &d_Agerekli tipe sahip olmadığı için uyarı veya hata atmaz mı?
CaptainProton42

3
Bunu nasıl yorumladığınıza dikkat edin,
CUDA'yı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.