문자열 상수에서 'char *'로의 변환이 C에서는 유효하지만 C ++에서는 무효 인 이유


163

C ++ 11 표준 (ISO / IEC 14882 : 2011)의 내용은 다음과 § C.1.1같습니다.

char* p = "abc"; // valid in C, invalid in C++

C ++의 경우 문자열 리터럴에 대한 포인터는 수정하려고하면 충돌이 발생하기 때문에 유해합니다. 그러나 C에서 왜 유효합니까?

C ++ 11도 말합니다 :

char* p = (char*)"abc"; // OK: cast added

즉, 캐스트가 첫 번째 명령문에 추가되면 유효합니다.

캐스트가 C ++에서 두 번째 명령문을 유효하게 만드는 이유는 무엇이며 첫 번째 명령문과 어떻게 다른가요? 여전히 해롭지 않습니까? 그렇다면 표준에서 괜찮다고 말한 이유는 무엇입니까?


3
C ++ 11은 첫 번째 것을 허용하지 않습니다. 왜 C가 문자열 리터럴 유형을 char[]처음에 만들 었는지 전혀 모른다 . 두 번째는 const_cast변장입니다.
chris

4
이 규칙이 변경되면 깨질 수있는 레거시 C 코드가 너무 많습니다.
Paul R

1
표준에서 두 번째는이라는 문구를 인용하십시오 OK.
Nawaz

13
C 언어에는 문자열 리터럴이 있었기 const때문에 반드시 그렇지는 않았습니다 const.
케이시

2
C 및 C ++를 사용하면 거의 모든 유형에서 다른 유형으로 캐스트 할 수 있습니다. 그렇다고 캐스트가 의미 있고 안전하다는 의미는 아닙니다.
Siyuan Ren

답변:


207

C ++ 03까지 첫 번째 예제는 유효했지만 더 이상 사용되지 않는 암시 적 변환을 사용했습니다. 문자열 리터럴은 char const *내용을 수정할 수 없으므로 정의되지 않은 동작이 발생하지 않기 때문에 유형으로 취급해야합니다 .

C ++ 11부터는 더 이상 사용되지 않는 암시 적 변환이 공식적으로 제거되었으므로 첫 번째 예와 같이 이에 의존하는 코드는 더 이상 컴파일되지 않아야합니다.

암시 적 변환이 제거되었지만 명시 적 변환은 여전히 ​​작동하므로 캐스트를 추가 할 수 있습니다. 나는 할 수 없습니다 , 그러나,이 "고정"코드를 살펴 보자.

코드를 올바르게 수정하려면 포인터 유형을 올바른 유형으로 변경해야합니다.

char const *p = "abc"; // valid and safe in either C or C++.

C ++에서 여전히 허용 된 이유 (아직 C에 있음) : 단순히 암묵적 변환에 의존하는 기존 코드가 많기 때문에 (적어도 공식적인 경고없이) 해당 코드를 깨는 것처럼 분명히 표준위원회에 보였다 나쁜 생각.


8
@rullof : 적어도 이식성에 관심이있는 코드에는 의미있는 유연성을 제공하지 못할 정도로 위험합니다. 문자열 리터럴에 쓰면 일반적으로 최신 OS에서 프로그램이 중단되므로 코드를 쓰려고 시도해도 의미있는 유연성이 추가되지 않습니다.
Jerry Coffin

3
코드는이 답변에 주어진 니펫은 char const *p = "abc";"유효하고 안전에 모두 C "유효하고 안전한 C ++ ",하지 C 또는 C ++".
Daniel Le

4
@DanielLe 두 문장 모두 같은 의미
를가집니다

3
오 주여! [혀에 혀를 단단히 삽입하십시오] 미안하지만 "또는"이 올바른 용어입니다. 코드는 C 또는 C ++로 컴파일 할 수 있지만 C 및 C ++로 동시에 컴파일 할 수는 없습니다. 둘 중 하나를 선택할 수 있지만 선택해야합니다. 한 번에 둘 다 가질 수는 없습니다. [정상적인 혀 작동을 재개하십시오].
Jerry Coffin

2
아니요, 두 가지 모두 가장 명확하고 가장 정확한 표현입니다. 올바른 의미를 전달 하거나 기술적으로 명확하지는 않습니다. 또는 혼자서는 틀림없이 잘못되었습니다 ( A 또는 BA 및 B와 같지 않습니다 ).
Apollys는 Monica

15

역사적 이유로 C에서는 유효합니다. C는 전통적으로 문자열 리터럴의 유형이 char *아닌 이라고 지정 const char *했지만 실제로는 수정할 수 없다고 말하여 규정했습니다.

캐스트를 사용할 때 기본적으로 기본 유형 일치 규칙보다 더 잘 알고 있다고 컴파일러에 알리고 할당을 확인합니다.


3
그것은이었다 char[N]과로 변경되었습니다 const char[N]. 크기 정보가 첨부되어 있습니다.
chris

1
C에서 문자열 리터럴의 타입은 char[N]아니지만 char*예를 들면 "abc"이다char[4]
Grijesh 차우

2

strdup 을 사용할 수도 있습니다 .

char* p = strdup("abc");
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.