C에서 'char **'를 'const char * const *'로 변환 할 수없는 이유는 무엇입니까?
다음 코드 조각은 (올바르게) C에서 경고를 표시하고 C ++에서 오류를 표시합니다 (각각 gcc 및 g ++ 사용, 버전 3.4.5 및 4.2.1로 테스트 됨, MSVC는 신경 쓰지 않는 것 같습니다).
char **a;
const char** b = a;
나는 이것을 이해하고 받아 들일 수 있습니다.
이 문제에 대한 C ++ 솔루션은 b를 const char * const *로 변경하는 것입니다. 이렇게하면 포인터의 재 할당을 허용하지 않고 const 정확성을 피할 수 없습니다 ( C ++ FAQ ).
char **a;
const char* const* b = a;
그러나 순수 C에서 수정 된 버전 (const char * const * 사용)은 여전히 경고를 표시하며 이유를 이해할 수 없습니다. 캐스트를 사용하지 않고이 문제를 해결할 수있는 방법이 있습니까?
명확히하기 위해 :
1) 왜 이것이 C에서 경고를 생성합니까? 그것은 전적으로 const 안전해야하며 C ++ 컴파일러는 그것을 그렇게 인식하는 것 같습니다.
2) 내가 가리키는 문자를 수정하지 않을 것이라고 말하면서 (그리고 컴파일러가 강제하도록)이 char **를 매개 변수로 받아들이는 올바른 방법은 무엇입니까? 예를 들어, 함수를 작성하고 싶다면 :
void f(const char* const* in) {
// Only reads the data from in, does not write to it
}
그리고 char **에서 호출하고 싶었습니다. 매개 변수의 올바른 유형은 무엇입니까?
나는 몇 년 전에 똑같은 문제를 겪었고 끝없이 짜증을 냈습니다.
C의 규칙은 더 간단하게 언급된다 (즉, 그들은 변환 좋아하지 목록 예외 수행 char**
에를 const char*const*
). 결과적으로 허용되지 않습니다. C ++ 표준에서는 이와 같은 경우를 허용하는 더 많은 규칙을 포함했습니다.
결국 이것은 C 표준의 문제 일뿐입니다. 다음 표준 (또는 기술 보고서)에서이 문제를 해결하기를 바랍니다.
호환되는 것으로 간주 되려면 소스 포인터가 직전 간접 레벨에서 const 여야합니다. 따라서 이것은 GCC에서 경고를 제공합니다.
char **a;
const char* const* b = a;
그러나 이것은 :
const char **a;
const char* const* b = a;
또는 다음과 같이 캐스트 할 수 있습니다.
char **a;
const char* const* b = (const char **)a;
언급했듯이 f () 함수를 호출하려면 동일한 캐스트가 필요합니다. 내가 아는 한,이 경우 암시 적 변환을 수행 할 방법이 없습니다 (C ++ 제외).
그러나 순수한 C에서는 여전히 경고가 표시되며 이유를 이해할 수 없습니다.
이미 문제를 확인했습니다.이 코드는 상수가 아닙니다. "정확한 상수"는 const_cast
제거하는 C 스타일 캐스트를 제외하고는 해당 const 포인터 또는 참조를 통해 개체를 const
수정할 수 없음을 의미 const
합니다.
const
-correctness 의 값은 const
대부분 프로그래머 오류를 감지하는 데 있습니다. 무언가를으로 선언 const
하면 수정해서는 안된다고 생각하는 것입니다. 또는 적어도 const
버전에 대한 액세스 권한 만있는 사람은 수정할 수 없어야합니다. 중히 여기다:
void foo(const int*);
선언 된대로 인수가 가리키는 정수를 수정할 권한foo
이 없습니다 .
게시 한 코드 const
가 잘못된 이유가 확실하지 않은 경우 HappyDude의 코드와 약간 다른 다음 코드를 고려하십시오.
char *y;
char **a = &y; // a points to y
const char **b = a; // now b also points to y
// const protection has been violated, because:
const char x = 42; // x must never be modified
*b = &x; // the type of *b is const char *, so set it
// with &x which is const char* ..
// .. so y is set to &x... oops;
*y = 43; // y == &x... so attempting to modify const
// variable. oops! undefined behavior!
cout << x << endl;
비 const
유형은 const
명시 적 캐스트없이 데이터 유형의 우회를 방지하기 위해 특정 방식으로 만 const 유형으로 변환 할 수 있습니다 .
처음 선언 된 객체 const
는 특히 특별합니다. 컴파일러는 절대 변경되지 않는다고 가정 할 수 있습니다. 그러나 캐스트없이 b
의 값을 할당 할 수있는 경우 a
실수로 const
변수 를 수정하려고 할 수 있습니다. 이것은 컴파일러에게 요청한 검사를 중단 할뿐만 아니라 해당 변수 값을 변경하지 못하도록 허용 할뿐만 아니라 컴파일러 최적화를 중단 할 수도 있습니다!
일부 컴파일러에서는, 42
일부 43
에서는, 다른 컴파일러에서는 프로그램이 충돌합니다.
편집-추가 :
HappyDude : 귀하의 의견이 있습니다. C 언어 또는 사용중인 C 컴파일러 const char * const *
는 C ++ 언어가 처리하는 것과 근본적으로 다르게 처리합니다. 이 소스 행에 대해서만 컴파일러 경고를 침묵시키는 것을 고려해보십시오.
This is annoying, but if you're willing to add another level of redirection, you can often do the following to push down into the pointer-to-pointer:
char c = 'c';
char *p = &c;
char **a = &p;
const char *bi = *a;
const char * const * b = &bi;
It has a slightly different meaning, but it's usually workable, and it doesn't use a cast.
I'm not able to get an error when implicitly casting char** to const char * const *, at least on MSVC 14 (VS2k5) and g++ 3.3.3. GCC 3.3.3 issues a warning, which I'm not exactly sure if it is correct in doing.
test.c:
#include <stdlib.h>
#include <stdio.h>
void foo(const char * const * bar)
{
printf("bar %s null\n", bar ? "is not" : "is");
}
int main(int argc, char **argv)
{
char **x = NULL;
const char* const*y = x;
foo(x);
foo(y);
return 0;
}
Output with compile as C code: cl /TC /W4 /Wp64 test.c
test.c(8) : warning C4100: 'argv' : unreferenced formal parameter
test.c(8) : warning C4100: 'argc' : unreferenced formal parameter
Output with compile as C++ code: cl /TP /W4 /Wp64 test.c
test.c(8) : warning C4100: 'argv' : unreferenced formal parameter
test.c(8) : warning C4100: 'argc' : unreferenced formal parameter
Output with gcc: gcc -Wall test.c
test2.c: In function `main':
test2.c:11: warning: initialization from incompatible pointer type
test2.c:12: warning: passing arg 1 of `foo' from incompatible pointer type
Output with g++: g++ -Wall test.C
no output
I'm pretty sure that the const keyword does not imply the data can't be changed/is constant, only that the data will be treated as read-only. Consider this:
const volatile int *const serial_port = SERIAL_PORT;
which is valid code. How can volatile and const co-exist? Simple. volatile tells the compiler to always read the memory when using the data and const tells the compiler to create an error when an attempt is made to write to the memory using the serial_port pointer.
Does const help the compiler's optimiser? No. Not at all. Because constness can be added to and removed from data through casting, the compiler cannot figure out if const data really is constant (since the cast could be done in a different translation unit). In C++ you also have the mutable keyword to complicate matters further.
char *const p = (char *) 0xb000;
//error: p = (char *) 0xc000;
char **q = (char **)&p;
*q = (char *)0xc000; // p is now 0xc000
What happens when an attempt is made to write to memory that really is read only (ROM, for example) probably isn't defined in the standard at all.
참고URL : https://stackoverflow.com/questions/78125/why-cant-i-convert-char-to-a-const-char-const-in-c
'Programing' 카테고리의 다른 글
.NET Core로 이미지 조작 (0) | 2020.12.09 |
---|---|
오류 : com.google.gms : google-services : 4.2.0을 찾을 수 없습니다. (0) | 2020.12.09 |
MVC-RedirectToAction ()으로 데이터 전달 (0) | 2020.12.09 |
char의 길이는 정확히 8 비트입니까? (0) | 2020.12.09 |
파일 또는 디렉토리가 변경 될 때 쉘 스크립트를 실행하는 방법은 무엇입니까? (0) | 2020.12.09 |