2011-08-10 4 views
16

내 컴파일러 (GCC)가 암시 적으로 char**에서 const char**으로 캐스트하지 않는 이유는 무엇입니까?char **에서 const char ** 로의 암시 적 변환

THIE 다음 코드를

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

[Foo **'→'Foo const **'로 변환하는 중 오류가 발생하는 이유는 무엇입니까?] (http://www.parashift.com/c++-faq-lite/const-correctness.html#faq -18.17) – fredoverflow

+0

"암시 적 캐스트"같은 것이 없습니다. '캐스트 '는 변환을 지정하는 명시 적 연산자입니다. 암시 적 변환도있을 수 있습니다. ("캐스트"는 연산자이고 "변환"은 연산입니다.) –

+0

@ 키스 : 용어는 문제가되지 않는다고 생각합니다. 결국, 우리는 "상향식"이 아니라 "상향식"이라고 말합니다. 적어도, 나는 그것을 말한다. :-) –

답변

16

이러한 변환은 당신이 안전하지 않은 것 char*의 배열,에 const char*을 넣을 수 있도록합니다 :

#include <iostream> 

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

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

다음과 같은 오류를 제공합니다. print 당신은 할 수 : main 그것은 const가 아닌 (char*)이 될 것으로 예상하면서

thing[0] = "abc"; 

지금 argv[0]은 수정할 수 없습니다 리터럴 문자열을 가리 것이다. 따라서 유형 안전성을 위해이 변환은 허용되지 않습니다.

+0

아주 좋은 설명 내가 이런 식으로 생각하지 않았다, 감사합니다. 'char * const * thing'으로 변경하면 예상대로 작동합니다. 그렇지만'const char * const * thing'도 작동해야하지만 그렇지 않습니다. 그것에 대한 더 많은 정보를 얻으려면 정말 좋을 것 같습니다. – nert

+0

C++에서는 작동하지만 C에서는 그렇지 않습니다. 따라서 어떤 질문도 찾을 수 없기 때문에 새로운 질문을 게시했습니다. https://stackoverflow.com/questions/35319842/why-c-doesnt-allow-implicit -conversion-from-char-to-const-char-const- – nert

6

@Fred Overflow 's link to the FAQ은 완전한 대답입니다. 그러나 (미안 마샬) 가장 명확한 설명은 아닙니다. 내 것이 더 명확한지는 모르지만 나는 그렇게 희망한다. pchar* 포인터 인 경우


문제는 그 다음 그것이 가리키는 것 어떤을 수정 에 사용할 수있다.

그리고 당신은 p을 가리키는 포인터 pp을 얻을 수 있지만, 유형 char const**pp와 함께, 당신은 pconst char의 주소를 할당 할 pp를 사용할 수 있다면.

그런 다음 p을 사용하여 const char을 수정할 수 있습니다. 또는 당신은 그렇게 생각할 것입니다. 하지만 const char은 읽기 전용 메모리 및 hellip에있을 수도 있습니다. 코드에서

: 실제 컴파일되지 않는 코드 솔루션, 중 & hellip으로

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

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


;

#include <iostream> 

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

int main(int argc, char** argv) { 
    print(argv); // Dang, doesn't compile! 
} 

그냥 & hellip;

#include <iostream> 

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

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

건배 & HTH.,

+0

이 스레드는 C 및 C++ 게시물에서 중복으로 링크되기 때문에 마지막 트릭은 C에서 작동하지 않습니다. C에서 작동하지 않는다면 아마도 표준위원회의 감독 일 뿐이다). –

+0

@MattMcNabb는 C 태그를 * 추가했습니다. 이 대답은 내가 그것을 썼을 때 좋았습니다. C에서는 작동하지 않지만 Pascal에서는 작동하지 않으며 Haskell이나 다른 언어에서 태그를 추가 할 수 없습니다. –

3

주,

void dosmth(const char** thing); 

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

이 금지되어 있지만, 당신은 당신이 어떻게 든 원하는 아마도 무엇을 어떤

void dosmth(const char* const* thing); 

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

을해야 할 수있다.여기에서 요점은 thingconst char* 배열을 참조하며 그 자체는 변경 가능하지 않고 참조 된 값 char은 그 자체로 불변임을 나타냅니다. 따라서 "을보고 있지만 변경하지 않으려면"시나리오의 경우 const char* const*을 사용할 유형입니다.

참고 : const 수정자를 가능한 한 왼쪽으로 쓰려고 시도하는 것이 더 일반적인 (그러나 내 의견은 열등한) 표준을 사용했습니다. 개인적으로 나는 그 방법이 훨씬 더 간결하므로 const char* const* 대신 char const* const*을 쓰는 것이 좋습니다.

+0

나는 또한 이것이 잘 작동한다고 생각했지만, gcc는 거기에 있지 않은 첫번째 const를 원한다. 특히 :'const char * const * thing'은 에러를 발생 시키지만,'char * const * thing'은 에러를 발생시키지 않습니다. – nert

+0

그래서 C++에서는 작동하지만 C에서는 그렇지 않습니다. 따라서 어떤 질문도 찾을 수 없기 때문에 새로운 질문을 게시했습니다. https://stackoverflow.com/questions/35319842/why-c-doesnt-allow-implicit -conversion-from-char-to-const-char-const- 및 – nert