복잡한 선언문을 읽기 쉬운 규칙?
복잡한 포인터 선언문을 읽는 경우 오른쪽-왼쪽 규칙이 있다.
그러나 이 규칙은 읽는 법을 언급하지 않는다.const
수식어
예를 들어, 간단한 포인터 선언에서,const
다음과 같은 여러 가지 방법으로 적용할 수 있다.
char *buffer; // non-const pointer to non-const memory
const char *buffer; // non-const pointer to const memory
char const *buffer; // equivalent to previous declartion
char * const buffer = {0}; // const pointer to non-const memory
char * buffer const = {0}; // error
const char * const buffer = {0}; // const pointer to const memory
이제 의 사용은 어떨까.const
포인터 선언으로?
char **x; // no const;
const char **x;
char * const *x;
char * * const x;
const char * const * x;
const char * * const x;
const char * const * const x;
그리고 그 선언문을 읽기 쉬운 규칙은 무엇인가?어떤 선언이 이치에 맞는가?
두 가지 실제 세계 사례
그 방법은 다음과 같다.const char **
명령행 인수를 제공하려면(llvm clang 소스).
의 인수 벡터 매개변수는 다음과 같이 선언된다.
int getopt(int argc, char * const argv[], const char *optstring);
어디에char * const argv[]
와 같다char * const * argv
그런 맥락에서
두 함수는 동일한 개념(논쟁을 제공하기 위한 문자열의 포인터 벡터)을 사용하고 선언이 다르므로 분명한 질문은 다음과 같다.그들은 왜 다른가?하나가 다른 하나보다 더 말이 되는가?
목적은 다음과 같아야 한다.그const
수정자는 함수가 이 벡터의 문자열을 조작하지 않으며 벡터의 구조를 변경하지 않음을 명시해야 한다.
그const
수식어는 사소한 것이다. 수식어는 수식어가 아닌 다른 수식어가 없는 한 수식어가 앞에 오는 것을 수정한다.자:
char const* buffer; // const modifies char
char* const buffer; // const modifies *
, 등. 일반적으로는 앞이 보이지 않는 형태는 피하는 것이 좋다.const
, 그러나 실제로는, 당신은 그들을 보게 될 것이기 때문에, 당신은 어떤 타입도 그 앞에 있지 않을 때 기억해야 한다.const
첫 번째 타입의 뒤에서 논리적으로 움직여야 한다.자:
const char** buffer;
사실:
char const** buffer;
, 즉, const char에 대한 포인터.
마지막으로 함수 선언에서 a[]
…으로 읽은 후에.*
(또한, 이런 오해의 소지가 있는 표기법은 피하는 것이 좋을 것 같지만, 곧 보게 되므로 반드시 대처해야 한다.)자:
char * const argv[], // As function argument
다음과 같은 경우:
char *const * argv,
철자를 가리키는 항성 포인터
(질문의 다른 측면에 초점을 맞추려고 시도 중)
법관선언에 대한 엄지의 법칙은 그것을 오른쪽에서 왼쪽으로 읽고, 그리고 왼쪽에서 읽는 것이다.const
다음 토큰을 수정하다예외:선언의 시작에const
이전 토큰을 수정하다
이 예외에는 근거가 있다 - 기본 선언에 대한const char c
보다 더 자연스러운 사람을 찾는다.char const c
- 그리고 의 전구적인 형태인 것으로 보고되고 있다.const char c
최후의 심판 규칙보다 앞서다
선택권을 얻다
int getopt(int argc, char * const argv[], const char *optstring);
또는
int getopt(int argc, char * const * argv, const char *optstring);
은... 그 말은...argv
일정하지 않은 문자열의 포인터의 등축 벡터에 대한 포인터.
그러나 누군가는 다음과 같은 선언을 예상할 것이다.
int getopt(int argc, char const * const * argv, const char *optstring);
(경구 벡터에 대해 등구 문자열로 표시)
왜냐하면getopt()
argv를 통해 참조되는 문자열을 변경해서는 안 된다.
적어도char **
(에 사용된 바와 같이)main()
)은(는) 다음으로 자동 변환됨char * const * argv
.
클랑
ASTUnit::LoadFromCommandLine(..., const char **argv, ...);
은... 그 말은...argv
항상 문자열에 대한 포인터의 일정하지 않은 배열의 포인터.
다시 한 번 예상할 수 있을 것이다.const char * const *argv
위와 같은 이유로
하지만 이것이 더 눈에 띄는 이유는char **
로 변환되지 않음const char **
예)
int main(int argc, char **argv) {
const char **x = argv; // Compile error!
return 0;
}
컴파일 오류를 산출한다.
int main(int argc, char **argv) {
char * const *x = argv;
return 0;
}
그리고
int main(int argc, char **argv) {
const char * const *x = argv;
return 0;
}
하지마
참조URL: https://stackoverflow.com/questions/7526152/easy-rule-to-read-complicated-const-declarations
'IT이야기' 카테고리의 다른 글
V-bind 스토어 상태 변경 시 클래스를 업데이트하지 않음 (0) | 2022.04.23 |
---|---|
Vue를 사용하여 API를 사용한 일괄 업데이트 (0) | 2022.04.23 |
C에서 C++ 함수를 호출하는 방법은? (0) | 2022.04.23 |
vue 계산된 속성을 한 번만 실행하는 방법 (0) | 2022.04.23 |
테스트 라이브러리와 함께 적용되지 않는 SFC 스타일 (0) | 2022.04.23 |