2011-08-10 5 views
16

Derleyicim (GCC) neden örtülü olarak char**'ten const char**'e dönüştürülmez?Char ** 'den const char'e örtülü dönüştürme **

Şu kodu takip ediyor:

#include <iostream> 

void print(const char** thing) { 
    std::cout << thing[0] << std::endl; 
} 

int main(int argc, char** argv) { 
    print(argv); 
} 

Aşağıdaki hatayı veriyor:

oi.cpp: In function ‘int main(int, char**)’: 
oi.cpp:8:12: error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive] 
oi.cpp:3:6: error: initializing argument 1 of ‘void print(const char**)’ [-fpermissive] 
+7

[Neden Foo ** '→ Foo const **' dönüştüren bir hata alıyorum? (Http://www.parashift.com/c++-faq-lite/const-correctness.html#faq -18.17) – fredoverflow

+0

"Kapalı yayın" diye bir şey yoktur. Bir "cast", bir dönüşümü belirten açık bir operatördür. Ayrıca, örtülü dönüşümler de olabilir. ("cast" operatördür, "conversion" işlemidir.) –

+0

@Keith: Bence terminoloji bir problem değil. Sonuçta, "up-cast" ve "up-conversion" demiyoruz. Ya da en azından bunu söylüyorum. :-) –

cevap

16

Böyle bir dönüşüm Eğer güvensiz olacağını char* senin dizi içine bir const char* koymak için izin verecek:

#include <iostream> 

void print(const char** thing) { 
    std::cout << thing[0] << std::endl; 
} 

int main(int argc, char** argv) { 
    print(argv); 
} 

aşağıdaki hatayı verir. print size yapabileceği: main o const olmayan (char*) olmasını bekler iken

thing[0] = "abc"; 

Şimdi argv[0], değiştirilemez değişmez bir dize işaret olacaktır. Bu nedenle, tip güvenliği için bu dönüşüme izin verilmez.

+0

Çok güzel bir açıklama Bu şekilde düşünmedim, teşekkürler. 'Char * const * thing' olarak değiştirilmesi beklendiği gibi çalışır. Ancak o zaman da 'const char * const * thing' çalışması gerekir, ama yapmaz. Bunun hakkında daha fazla bilgi için harika olurdum. – nert

+0

Bu yüzden C++ için çalışıyor, ancak C için değil, bu yüzden bunun için yeni bir soru gönderdim çünkü herhangi bir cevap bulamadım: https://stackoverflow.com/questions/35319842/why-c-doesnt-allow-implicit -con-char-to-const-char-const-ve- – nert

6

@Fred Taşma en link to the FAQ tam cevabıdır. Ama (üzgünüm Marshall) en açık açıklama değil. Benimki daha açık mı bilmiyorum ama umarım öyle olur. p bir char* gösterici ise


şey o zaman o işaret ne olursa olsun değiştirmek için kullanılabilir, vardır.

Ve p işaret eden bir işaretçi pp elde edebilir, ancak tip char const** ait pp ile, o zaman p bir const char adresini atamak için pp kullanabilirsiniz eğer.

Ve bununla

, daha sonra const char değiştirmek için p kullanabilirsiniz. Ya da yapabileceğini düşünürdün. Ama bu const char bile salt okunur bellek ve hellip olabilir; kodunda

: pratik bir derleme değil Kodunuza çözümü, & hellip olarak

char const  c = 'a'; 
char*    p = 0; 
char const**  pp = &p;    // Not allowed. :-) 

*pp = &c;  // p now points to c. 
*p = 'b';  // Uh oh. 


;

just do & hellip;

#include <iostream> 

void print(char const* const* thing) 
{ 
    std::cout << thing[0] << std::endl; 
} 

int main(int argc, char** argv) 
{ 
    print(argv); // OK. :-) 
} 

Şerefe & hth.,

+0

-den-dönüşümü Bu iş parçacığı hem C hem de C++ iletilerinden kopyalar olarak bağlandığından, son numaranın C olarak çalışmadığına dikkat edin (bunun için iyi bir neden yok. C'de çalışmaz, muhtemelen standartlar komitesinin gözetimidir). –

+0

@MattMcNabb sadece * C etiketini ekledi. Bu cevap yazdığımda iyiydi ve tamamlandı. C için işe yaramıyor, Pascal için işe yaramıyor, Haskell için çalışmıyor ya da etiket eklediği başka bir dil var. –

3

Not

void dosmth(const char** thing); 

int main(int argc, char** argv) { 
    dosmth(argv); 

yasaklanmış olmasına rağmen, sen ve sen yine istediğini muhtemelen budur Hangi

void dosmth(const char* const* thing); 

int main(int argc, char** argv) { 
    dosmth(argv); 

yapmalıdır ki.Buradaki nokta, thing'un kendisinin immutable olduğu ve char referans değerlerinin kendilerinin immutable olduğu bir const char* dizisine değinmesidir. Yani, bir "bakmak, ancak değiştirmeyin" senaryosu, const char* const* kullanmak türüdür.

Not: const değiştiriciyi mümkün olduğunca sola yazmayı denerken daha yaygın (ama benim görüşüme göre) standardı kullandım. Şahsen, const char* const* yerine char const* const* yazmayı tavsiye ederim, çünkü bu şekilde daha detaylı.

+0

Bunun da işe yarayacağını düşündüm, ama gcc ilk yapının orada olmamasını istiyor. Özellikle: const const * const * thing 'bir hata verir, ancak' char * const * thing' değil. – nert

+0

Bu yüzden C++ için çalışıyor, ancak C için değil, bu yüzden bunun için yeni bir soru yayınladım çünkü herhangi bir cevap bulamadım: https://stackoverflow.com/questions/35319842/why-c-doesnt-allow-implicit -dönüşüm-den-kömürün-için-Kat-Char const-ve – nert