2016-12-05 1 views
2

const을 (를) 멀리 캐스팅하는 것이 불법입니까?언제 법적으로 합법적으로 또는 불법으로 캐스팅하고 있습니까? (gcc, clang 및 MSVC)

대부분의 경우 const은 컴파일러에 의해 시행되는 사용자를위한 단순한 주석입니다. 이 질문은 멀리 던지기 const가 엄격하게 불법이고 C99 표준의 어떤 부분이 그것을 금지하는지 묻습니다.

글로벌 범위의 const 함수 포인터가 때때로 gcc에 의해 인라인된다는 것을 관찰했기 때문에 어떤 경우에는 불법이라고 생각합니다. 이러한 함수 포인터가 나중에 프로그램에서 합법적으로 수정 될 수있는 경우이 최적화는 유효하지 않습니다. 덧붙여서 나는 멀리 던지기에 대한 설명을 읽었을 것입니다. const은 StackOverflow에서 불법이지만 그냥 찾을 수 없습니다. (대답은 const은 변수가 원래 const으로 선언되지 않은 경우에만 제외 될 수 있다고 생각합니다.)

C99 표준에 명시되어 있기를 바라고 있기 때문에이 C99 태그를 붙였습니다.하지만 대답은 C99의 gcc, clang 및 MSVC 구현에 공통된 동작을 설명 할 수 있습니다. 그러면 나에게도 충분합니다.

(분명히 이것은 매우 기본적인 질문이므로 C 표준 인에 대해 복제본을 찾지 못했습니다. 다른 사람이 정확한 복제본을 가리킬 수 있으면 투표를 닫을 수 있습니다. 이 질문 제목은 SSO가 이런 종류의 질문을하는 데 최소한 도움이된다고 생각합니다.)

+0

"표준이 허용하지 않는시기는 언제입니까?"또는 "이 기능이 작동하지 않는시기"를 묻는 중입니까? 전자에 대한 대답은 "거의 항상"입니다. 후자에 대한 대답은 "거의 절대"입니다. – aaaaaa123456789

+0

@ aaaaaa123456789이 질문에 대해서는 표준 (즉, 'languge-lawyer'태그)에 따라 답변을 원하지만, 언제 작동하는지에 대한 추가 논평은 신경 쓰지 않아도됩니다. (추신 : 나는 또 다른 단락을 당신의 의견 뒤에 덧붙여 편집했다.) 또한, "const"가 버려지는 것이 합법적이라고 생각할 때 "never never"가 올바른 답이라고 생각하지 않는다. (분명히 나는 ​​틀릴 수있다 - 그러므로 질문!) – Praxeolitic

+0

나는 그것이 언제 허용되는지 완전히 확신하지 못한다. 대부분의 경우, 그렇지 않습니다. 반면에 값은 리터럴이 아니며 (일반적으로 리터럴은 소스 코드에 포함되어 있으며 대부분의 OS는 메모리의 프로그램 코드를 수정하지 못하게합니다). – aaaaaa123456789

답변

11

결코 불법적 인 행위를해서는 안됩니다. 당신은 자유롭고 합법적으로 원하는만큼 할 수 있습니다. 그러나 을 시도하면 const38을 제거한 후 뾰족한 객체가 정의되지 않은 동작으로 이어질 수 있습니다 (또는 상황에 따라 다를 수 있음). 시도 비와 좌변의 사용을 통해 const를 수식 유형으로 정의 객체를 변경하려고했을 경우

C99 명확하게

6.7.3 유형 예선

5을 말한다 -const-qualified 형식 인 경우 동작은 정의되지 않습니다.

(C11에서는 6.7.3/6).

C (및 C++)의 const는 두 개의 독립적 매우 다른 역할에 사용되는

참고 : CONST 의 적격 객체 자체 및 오브젝트에 액세스 경로 의 CONST 적격. 자체 이것은

*(int *) p = 6; // nothing formally wrong with it 

에서 const되지

const int a = 42; // `a` is a const-qualifiet object 

int b = 5;   // `b` is not const-qualified 
const int *p = &b; // `*p` is a const-qualified access path to `b` 

후자의 경우, const와 법적 멀리 캐스팅 할 수 있고, 생성 된 비 CONST 액세스 경로가 객체를 수정하는 데 사용될 수있는 오브젝트를 구비 우리가 언어로 constence를 버리는 능력을 가지고있는 바로 그 이유.CONST 객체가 실제로 읽기 전용 메모리에 위치 할 수 -

그러나 전 (개체 자체의 const와는)

*(int *) &a = 43; // undefined behavior 

이유는 아주 간단하다 재정의 할 수 없습니다. 그리고 컴파일러가 아니더라도 컴파일러는 객체의 값이 변하지 않는다는 가정하에 코드를 컴파일 할 수 있습니다.

이것은

const int *const cp = &b; 

같은 선언이 두 const 상당히 다른 의미를 가지고 있다는 것을 의미한다. 첫 번째 (가장 왼쪽) 것은 "부드러운"const이며 조건이 맞으면 재정의 할 수 있습니다. 그러나 두 번째 const은 무시할 수없는 "하드"const입니다.

따라서 "const은 컴파일러에 의해 시행되는 사용자를위한 단순한 주석"이라고 말하면 액세스 경로의 const 자격에 대해서만 해당됩니다. 객체 자체의 const-qualifications에 관해서는 일반적으로 순전히 개념적으로 컴파일러가 시행하는 "주석"보다 훨씬 더 많습니다.

+0

좋은 답변, 고마워. 그냥 분명히하기 위해 남은 대답은 당신이 준 표준에서 따옴표를 인용 한 것입니까? 당신이 설명하는 구별은 * 객체 자체의 const-qualification과 객체에 대한 접근 경로의 const-qualification은 훌륭하고 명확하지만 "const access-path"와 같은 문구가 나는 다른 사람들이 이해할 것으로 기대해야하는 표준입니다. – Praxeolitic

+0

@Praxeolitic : 나는 C++ 표준에서 "접근 경로"라는 개념을 빌렸다. 공식적인 정의없이 동등한 문맥에서 구어체로 사용된다. 따라서 이것은 공식적인 용어가 아니라 오히려 자명 한 것입니다. – AnT

+0

불행히도 C 표준은 "대상"을 구성하는 것에 대해 다소 어둡습니다. 'int * p = calloc (1, sizeof (int));','* p'에 의해 식별되는 객체의 타입으로 간주되는 것은 무엇입니까? 'int','int const' 또는 다른 것입니까? – supercat

관련 문제