const int *, const int * const 및 int const *의 차이점은 무엇입니까?


1356

사용하는 방법까지 난 항상 혼란 const int*, const int * const그리고 int const *정확하게. 할 수있는 것과 할 수없는 것을 정의하는 일련의 규칙이 있습니까?

과제, 기능 전달 등의 측면에서 모든 할 일과하지 말아야 할 것을 알고 싶습니다.


175
"Clockwise / Spiral Rule" 을 사용하여 대부분의 C 및 C ++ 선언을 해독 할 수 있습니다 .
James McNellis

52
cdecl.org 는 C 선언을 자동 번역하는 훌륭한 웹 사이트입니다.
Dave Gallagher

6
@Calmarius : type-name이있는 곳에서 시작하고, 할 수 있으면 오른쪽으로 이동하고, 필요할 때 왼쪽으로 이동하십시오 . int *(*)(char const * const). 괄호의 오른쪽에서 *시작한 다음 왼쪽으로 이동해야합니다 pointer. 괄호 밖에서 우리는 오른쪽으로 움직일 수 있습니다 pointer to function of .... 그런 다음 왼쪽으로 이동해야합니다 pointer to function of ... that returns pointer to int. 매개 변수 ( ...) 를 확장하려면 반복 하십시오 pointer to function of (constant pointer to constant char) that returns pointer to int. 파스칼과 같이 읽기 쉬운 언어로 된 한 줄짜리 선언은 무엇입니까?
Mark K Cowan

1
@MarkKCowan Pascal에서는 다음과 같습니다 function(x:^char):^int. 함수 유형은 함수에 대한 포인터를 의미하므로 지정할 필요가 없으며 파스칼은 const 정확성을 강요하지 않습니다. 왼쪽에서 오른쪽으로 읽을 수 있습니다.
Calmarius

5
"const"의 왼쪽에있는 첫 번째 것은 상수입니다. "const"가 가장 왼쪽에있는 것이라면, 오른쪽에있는 첫 번째 것은 상수입니다.
Cupcake

답변:


2208

시계 방향 / 나선형 규칙에 따라 뒤로 읽습니다 .

  • int* -int에 대한 포인터
  • int const * -const int에 대한 포인터
  • int * const -int에 대한 const 포인터
  • int const * const -const int에 대한 const 포인터

이제 첫 번째 const는 유형의 양쪽에있을 수 있습니다.

  • const int * == int const *
  • const int * const == int const * const

정말로 미쳐 가고 싶다면 다음과 같이 할 수 있습니다.

  • int ** -int를 가리키는 포인터
  • int ** const -int에 대한 포인터에 대한 const 포인터
  • int * const * -int에 대한 const 포인터에 대한 포인터
  • int const ** -const int에 대한 포인터에 대한 포인터
  • int * const * const -int에 대한 const 포인터에 대한 const 포인터
  • ...

그리고 우리는 다음의 의미를 명확하게합니다 const.

int a = 5, b = 10, c = 15;

const int* foo;     // pointer to constant int.
foo = &a;           // assignment to where foo points to.

/* dummy statement*/
*foo = 6;           // the value of a can´t get changed through the pointer.

foo = &b;           // the pointer foo can be changed.



int *const bar = &c;  // constant pointer to int 
                      // note, you actually need to set the pointer 
                      // here because you can't change it later ;)

*bar = 16;            // the value of c can be changed through the pointer.    

/* dummy statement*/
bar = &a;             // not possible because bar is a constant pointer.           

foo상수 정수에 대한 변수 포인터입니다. 이것은 당신이 가리키는 것을 변경하지만 당신이 가리키는 값은 변경할 수 없습니다. 가장 자주 이것은 C 스타일 문자열에서 볼 수 있습니다 const char. 가리키는 문자열을 변경할 수 있지만 이러한 문자열의 내용을 변경할 수는 없습니다. 문자열 자체가 프로그램의 데이터 세그먼트에 있고 변경해서는 안되는 경우에 중요합니다.

bar변경할 수있는 값에 대한 상수 또는 고정 포인터입니다. 이것은 여분의 구문 설탕이없는 참조와 같습니다. 이 사실 때문에 일반적으로 T* const포인터를 허용하지 않는 한 포인터 를 사용하는 참조를 사용합니다 NULL.


481
'const'가 포인터 또는 지정된 데이터에 적용되는지 여부를 발견하는 방법을 기억하는 데 도움이되는 경험칙을 추가하고 싶습니다. 'const int * foo')-올바른 부분에 있으면 ( 'int * const bar') 지정된 데이터에 속합니다. 포인터에 관한 것입니다.
Michael

14
@Michael : const 규칙을 기억 / 이해하기위한 간단한 규칙에 대해 Michael에게 전합니다.
sivabudh

10
@ Jeffrey : 괄호가없는 한 뒤로 읽으십시오. 그럼 ... typedef 사용
Mooing Duck

12
+1, 더 나은 요약 될 것이지만 : 읽기 포인터 선언 뒤로 , 수단, 가까운 @Michael의 문 것을 : 상기 일반 왼쪽에서 오른쪽으로 읽는 중지 첫번째 별표.
Wolf

3
@gedamial, 잘 작동하지만 "const 포인터"를 재 할당 할 수 없기 때문에 선언 할 때 할당해야합니다. const int x = 0; const int *const px = &x; const int *const *const p = &px;잘 작동합니다.
RastaJedi

356

시계 방향 / 나선 규칙에 대해 모르는 경우 : 변수 이름에서 시작하여 시계 방향으로 (이 경우에는 뒤로) 다음 포인터 또는 유형으로 이동하십시오 . 식이 끝날 때까지 반복하십시오.

데모는 다음과 같습니다.

int에 대한 포인터

int const에 대한 const 포인터

int const에 대한 포인터

const int에 대한 포인터

int에 대한 const 포인터


8
@Jan 복잡한 예제의 링크에 권한이 없습니다. 여기에 직접 게시하거나보기 제한을 제거 할 수 있습니까?
R71

8
@Rog 그것은 모든 공개 액세스 권한을 가지고 있었지만 불행히도 기사를 쓰지 않았고 액세스 권한이 없습니다. 그러나 다음은 여전히 ​​작동하는 기사의 아카이브 버전입니다. archive.is/SsfMX
Jan Rüegg

8
복잡한 예제는 여전히 오른쪽에서 왼쪽이지만 정상적으로 괄호를 포함합니다. 시계 방향의 나선형은 그다지 쉽지 않습니다.
Matthew 읽기

4
궁극적 인 예 : void (*signal(int, void (*fp)(int)))(int);archive.is/SsfMX
naXa

3
이 규칙에 의존하지 마십시오. 이것은 보편적이지 않습니다. 실패하는 경우가 있습니다.
haccks

150

나는 모든 것이 여기에 이미 대답했다고 생각하지만, 나는 당신이 typedefs를 조심해야한다고 덧붙이고 싶다 ! 그들은 단지 텍스트를 대체하는 것이 아닙니다.

예를 들면 다음과 같습니다.

typedef char *ASTRING;
const ASTRING astring;

의 유형이 astring있다 char * const, 없다 const char *. 이것이 제가 항상 const타입의 오른쪽에 두는 경향이 있고 시작하지 않는 이유 중 하나 입니다.


20
그리고 이것은 포인터를 typedef하지 않는 이유입니다. 나는 typedef int* PINT(C의 관행에서 나온 것으로 가정하고 많은 개발자들이 계속 그렇게한다고 생각한다) 와 같은 이점을 보지 못합니다 . 우수함, 그 대체 *와 함께 P, 그것은 입력 속도를, 플러스 당신이 언급 문제를 도입하지 않습니다.
Mephane

1
@Mephane-알 수 있습니다. 그러나 나에게는 예외적 인 구문 규칙을 사용하지 않고 예외적 인 구문 규칙 ( "const"배치에 대해)을 계속 사용하기 위해 멋진 언어 기능을 피하는 것이 역행적인 것처럼 보이므로이 언어 기능을 안전하게 사용할 수 있습니다 .
TED

6
@Mephane PINT은 실제로 typedef의 다소 바보 같은 사용법입니다. 특히 cuz는 시스템 저장소가 맥주를 메모리로 사용한다고 생각합니다. typedef는 함수에 대한 포인터를 다루는 데 매우 유용합니다.
ApproachingDarknessFish 21

5
트윗 담아 가기 그게 없으면, 나는 모든 typedefed 사람들과 엉망 한 것 PVOID, LPTSTRWin32 API를에 물건!
David Lee

2
@Mephane : 형식을 허용하도록 작성된 특정 레거시 매크로를 사용할 때 pSomething을 두 번 사용해야했지만 형식이 단일 영숫자 식별자가 아닌 경우 분리됩니다. :)
Groo

56

거의 모든 사람들이 지적한 것처럼 :

무슨 사이의 차이점 const X* p, X* const p그리고 const X* const p?

포인터 선언을 오른쪽에서 왼쪽으로 읽어야합니다.

  • const X* p "p는 const 인 X를 가리킴"을 의미합니다. X 객체는 p를 통해 변경할 수 없습니다.

  • X* const p "p는 const가 아닌 X에 대한 const 포인터"를 의미합니다. 포인터 p 자체는 변경할 수 없지만 p를 통해 X 객체를 변경할 수 있습니다.

  • const X* const p "p는 const 인 X에 대한 const 포인터"를 의미합니다. 포인터 p 자체를 변경할 수 없으며 p를 통해 X 객체를 변경할 수도 없습니다.


3
그 잊지 마세요 const X* p;== X const * p;등의"p points to an X that is const": the X object can't be changed via p.
제시 치솜

간단하고 좋은 설명!
Edison Lo

50
  1. 상수 참조 :

    상수 인 변수 (여기서 int)에 대한 참조입니다. 참조는 실제 값보다 크기가 작기 때문에 변수를 참조로 주로 전달하지만 부작용이 있으며 이는 실제 변수의 별칭과 유사하기 때문입니다. 별칭에 대한 전체 액세스를 통해 실수로 주요 변수를 변경할 수 있으므로 이러한 부작용을 방지하기 위해 변수를 일정하게 만듭니다.

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
  2. 상수 포인터

    상수 포인터가 변수를 가리키면 다른 변수를 가리킬 수 없습니다.

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
  3. 상수를 가리키는 포인터

    변수의 값을 변경할 수없는 포인터를 상수에 대한 포인터라고합니다.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
  4. 상수에 대한 상수 포인터

    상수에 대한 상수 포인터는 가리키는 주소를 변경하거나 해당 주소에 유지 된 값을 변경할 수없는 포인터입니다.

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error

20

일반적인 규칙은 const키워드가 바로 앞에 오는 항목에 적용된다는 것입니다. 예외적으로 시작은 const다음에 적용됩니다.

  • const int*"상수 int에 대한 포인터"int const* 와 동일 하고 의미 합니다.
  • const int* const"상수 int에 대한 상수 포인터"int const* const 와 동일 하고 의미 합니다.

편집 : 해야 할 일과하지 말아야 할 것입니다. 이 답변 으로 충분하지 않으면 원하는 것에 대해 더 정확할 수 있습니까?


19

이 질문은 내가 왜 내 질문에서 언급 한 방식 이 형식 ID 허용 후 const 인 것을 좋아하는지 정확하게 보여줍니다 .

즉, 내가 규칙을 기억하는 가장 쉬운 방법을 찾아 "CONST는"가는 것입니다 가 적용되는 것. 따라서 귀하의 질문에서 "int const *"는 int가 상수임을 의미하고 "int * const"는 포인터가 상수임을 의미합니다.

누군가가 맨 앞에 배치하기로 결정한 경우 (예 : "const int *"),이 경우 특별한 예외로 그 뒤에있는 것에 적용됩니다.

많은 사람들이이 예외를 더 좋아 보인다고 생각하기 때문에이 예외를 사용하는 것을 좋아합니다. 나는 그것이 예외이기 때문에 그것을 싫어하여 혼란스럽게합니다.


2
나는이 문제로 찢어졌습니다. 논리적으로 말이됩니다. 그러나 대부분의 C ++ 개발자는 작성 const T*하고 더 자연스럽게되었습니다. T* const어쨌든 얼마나 자주 사용합니까? 일반적으로 참조는 정상적으로 작동합니다. 나는 원할 때이 모든 것을 한 번에 boost::shared_ptr<const T>썼고 대신 썼다 const boost::shared_ptr<T>. 약간 다른 맥락에서 같은 문제.
매트 가격

실제로 상수를 사용하는 것보다 상수 포인터를 더 자주 사용합니다. 또한 포인터에 대한 포인터가있는 경우 어떻게 반응 할 것인지 생각해야합니다. 물론 드물지만 이러한 상황을 applomb으로 처리 할 수있는 방식으로 생각하는 것이 좋습니다.
TED

1
유형의 오른쪽에 const를 배치하면 얻을 수있는 또 다른 장점은 이제 왼쪽에있는 모든 const것이 const 인 유형이고 오른쪽에있는 모든 것이 실제로는 const라는 것입니다. 가지고 int const * const * p;예를 들어. 아니, 나는 보통 그렇게 쓰지 않습니다. 이것은 단지 예일뿐입니다. 첫 번째 const: int 유형이고 const 인 int는의 내용 인 const 포인터의 내용입니다 p. 두 번째 const : type은 constint를 가리키는 포인터 이고 const oblect는p
dgnuff

18

의 간단한 사용 const.

가장 간단한 용도는 명명 된 상수를 선언하는 것입니다. 이를 위해 상수는 변수 인 것처럼 선언하지만 const앞에 추가 합니다. 물론 생성자를 변경하면 나중에 나중에 값을 설정할 수 없기 때문에 생성자에서 즉시 초기화해야합니다. 예를 들면 다음과 같습니다.

const int Constant1=96; 

Constant1값 96으로 상상할 수없는 정수 상수를 만듭니다 .

이러한 상수는 프로그램에서 사용되는 매개 변수에 유용하지만 프로그램을 컴파일 한 후에는 변경할 필요가 없습니다. C 프리 프로세서 #define명령에 비해 프로그래머에게는 이점이 있는데, 이는 메인 컴파일러에 도달하기 전에 프리 프로세서에 의해 프로그램 텍스트로 대체되는 것이 아니라 컴파일러 자체에 의해 이해되고 사용되므로 오류 메시지가 훨씬 유용합니다.

또한 포인터와 함께 작동하지만 const포인터 또는 포인터가 일정한지 또는 둘 다를 결정할지 신중 해야합니다. 예를 들면 다음과 같습니다.

const int * Constant2 

Constant2상수 정수에 대한 변수 포인터 임을 선언 하고 다음을 수행합니다.

int const * Constant2

동일한 구문을 사용하는 대체 구문입니다.

int * const Constant3

Constant3변수 정수에 대한 상수 포인터 임을 선언 하고

int const * const Constant4

Constant4상수 정수에 대한 상수 포인터 임을 선언합니다 . 기본적으로 'const'는 바로 왼쪽에있는 모든 것에 적용됩니다 (어떤 경우에도 오른쪽에있는 것에 적용되지 않는 경우 제외).

심판 : http://duramecho.com/ComputerInformation/WhyHowCppConst.html


9

C ++ Guru Scott Meyers 가이 을 발견 할 때까지 나는 당신과 같은 의심을 가졌습니다 . 이 책에서 사용에 대한 자세한 내용은 세 번째 항목을 참조하십시오 const.

이 조언을 따르십시오

  1. 단어 const가 별표 왼쪽에 나타나면 지시하는 것은 일정합니다
  2. 단어 const가 별표 오른쪽에 나타나면 포인터 자체가 일정합니다
  3. 경우 const양쪽에 나타나면, 모두 일정

7

간단하지만 까다 롭습니다. 우리가 바꿀 수 있습니다 const모든 데이터 유형 (로 규정 int, char, float, 등).

아래 예제를 보자.


const int *p==> *p은 읽기 전용입니다 [ p상수 정수에 대한 포인터입니다]

int const *p==> *p은 읽기 전용입니다 [ p상수 정수에 대한 포인터입니다]


int *p const==> 잘못된 진술. 컴파일러에서 구문 오류가 발생합니다.

int *const p==> p는 읽기 전용입니다 [ p정수에 대한 상수 포인터]. p여기의 포인터 는 읽기 전용이므로 선언과 정의는 동일한 위치에 있어야합니다.


const int *p const ==> 잘못된 진술. 컴파일러에서 구문 오류가 발생합니다.

const int const *p ==> *p는 읽기 전용입니다

const int *const p1 ==> *p이고 p읽기 전용입니다 [ p상수 상수에 대한 상수 포인터]. p여기의 포인터 는 읽기 전용이므로 선언과 정의는 동일한 위치에 있어야합니다.


int const *p const ==> 잘못된 진술. 컴파일러에서 구문 오류가 발생합니다.

int const int *p ==> 잘못된 진술. 컴파일러에서 구문 오류가 발생합니다.

int const const *p ==> *p는 읽기 전용이며 다음과 같습니다.int const *p

int const *const p ==> *p이고 p읽기 전용입니다 [ p상수 상수에 대한 상수 포인터]. p여기의 포인터 는 읽기 전용이므로 선언과 정의는 동일한 위치에 있어야합니다.


6

C ++에서 const 정확성을 둘러싼 많은 다른 미묘한 점이 있습니다. 여기에 대한 질문은 단순히 C에 관한 것이지만 태그가 C ++이므로 관련 예제를 제공합니다.

  • 종종 문자열과 같은 큰 인수를 전달 TYPE const &하여 객체가 수정되거나 복사되는 것을 방지합니다. 예 :

    TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }

    그러나 TYPE & const참조는 항상 const이기 때문에 의미가 없습니다.

  • 클래스를 수정하지 않는 클래스 메서드에는 항상 레이블을 지정해야합니다 const. 그렇지 않으면 TYPE const &참조 에서 메서드를 호출 할 수 없습니다 . 예 :

    bool TYPE::operator==(const TYPE &rhs) const { ... }

  • 리턴 값과 메소드가 모두 const이어야하는 일반적인 상황이 있습니다. 예 :

    const TYPE TYPE::operator+(const TYPE &rhs) const { ... }

    실제로 const 메소드는 내부 클래스 데이터를 비표준 참조로 반환해서는 안됩니다.

  • 결과적으로 const 오버로딩을 사용하여 const와 non-const 메소드를 모두 만들어야하는 경우가 종종 있습니다. 예를 들어을 정의 T const& operator[] (unsigned i) const;하면 다음과 같이 비 const 버전을 원할 것입니다.

    inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }

Afaik, C에는 const 함수가 없으며 멤버가 아닌 함수 자체는 C ++에서 const 일 수 없으며 const 메소드에는 부작용이있을 수 있으며 컴파일러는 const 함수를 사용하여 중복 함수 호출을 피할 수 없습니다. 실제로, 단순한 int const &참조 조차도 그것이 참조하는 가치가 다른 곳에서 변경되는 것을 목격 할 수 있습니다.


6

C 및 C ++ 선언 구문은 원래 설계자에 의해 실패한 실험으로 반복해서 설명되었습니다.

대신, 타입 의 이름을 "pointer to Type"로 지정 하겠습니다 . 나는 그것을 부를 것이다 Ptr_:

template< class Type >
using Ptr_ = Type*;

이제 Ptr_<char>에 대한 포인터입니다 char.

Ptr_<const char>에 대한 포인터 const char입니다.

그리고 const Ptr_<const char>A는 const포인터 const char.

그곳에.

여기에 이미지 설명을 입력하십시오


3
첫 문장에 대한 인용문이 있습니까?
sp2danny

@ sp2danny : 인터넷 검색 "C는 실험을 실패 구문"단지 그가 표현 비얀 스트로브 스트 룹과의 인터뷰 다수의 최대 기침 그의 그 방향으로 의견을, 예를 들면 Slashdot의 인터뷰에서 "나는 C 선언자 구문 실패 실험을 생각을." 그래서 나는 C의 오리지널 디자이너의 관점에 대한 주장에 대한 언급이 없습니다. 나는 그것이 충분히 강력한 연구 노력으로 찾을 수 있거나 단순히 물어 보는 것만으로 반증 될 수 있다고 생각합니다. 그러나 나는 그것이 지금의 방식보다 나을 것이라고 생각합니다. 주장의 그 부분으로, 여전히 결정되지 않았을 가능성이 있습니다 :)
건배와 hth. -Alf

1
"C 및 C ++ 선언 구문은 원래 설계자에 의해 실험 실패로 반복해서 설명되었습니다." C에 대한 잘못된 C에 대한 문장을 변경하거나 따옴표를 제공하십시오.
Stargateur

3
@Stargateur : 분명히 당신은 앞의 주석을 읽었으며 pedantry에 활용할 수있는 것을 발견했습니다. 당신의 인생과 행운을 빕니다. 어쨌든, 저 같은 노인들은 시간이 많이 걸리는 연구에 참여하지 않으면 우리가 증명할 수없는 많은 것을 기억합니다. 당신은 내 말을 할 수 있습니다.
건배와 hth. -Alf

1
@Stargateur "Sethi (...)는 간접 연산자가 접두사 대신 접미사 연산자로 사용 된 경우 중첩 된 선언과 표현식 중 많은 부분이 더 단순해질 것으로 예상했지만 변경하기에는 너무 늦었습니다." DMR에서 가져온 것입니다. 물론 DMR은 const와 volatile 키워드를 발명하지 않았으며 해당 페이지에서 입증 된 것처럼 C ++ / X3J11에서 나왔습니다.
Antti Haapala

6

나를 위해, const즉 왼쪽 또는 오른쪽 또는 왼쪽 및 오른쪽 둘 다에 나타나는 위치 *는 실제 의미를 파악 하는 데 도움 이 됩니다.

  1. const의 왼쪽은 *객체가 포인터가있다 가리키는 것을 나타냅니다 const객체입니다.

  2. const오른쪽의 A *는 포인터가 포인터임을 나타냅니다 const.

다음 표는 Stanford CS106L 표준 C ++ 프로그래밍 실험실 코스 리더에서 가져온 것입니다.

여기에 이미지 설명을 입력하십시오


3

모범 사례, 과제, 기능 매개 변수 등 두 번째 줄을 주로 다룹니다.

일반적인 연습. 할 수있는 모든 const것을 만들어보십시오 . 또는 다른 방법 const으로 시작하려면 모든 것을 시작으로 만든 다음 const프로그램이 작동하는 데 필요한 최소 세트를 제거하십시오 . 이것은 const-correctness를 얻는 데 큰 도움이 될 것이며 사람들이 수정하지 말아야 할 것에 미묘한 버그가 발생하지 않도록 보장 할 것입니다.

전염병처럼 const_cast <>를 피하십시오. 이에 대한 합법적 인 사용 사례는 하나 또는 두 가지이지만 매우 적습니다. const객체 를 변경하려는 경우 const첫 번째 속도로 객체를 선언 한 사람을 찾아서 그 문제를 논의하여 어떤 일이 발생해야하는지에 대한 합의에 도달하는 것이 좋습니다.

과제를 매우 깔끔하게 이끌어냅니다. 일정하지 않은 경우에만 무언가를 할당 할 수 있습니다. const 인 것을 할당하려면 위를 참조하십시오. 선언 int const *foo;int * const bar;다른 것들이 있음을 기억하십시오. const여기의 다른 답변은 그 문제를 훌륭하게 다루었으므로 다루지 않겠습니다.

기능 매개 변수 :

가치에 의한 전달 : 예 void func(int param)를 들어 , 발신 사이트에서 어떤 방식 으로든 상관하지 않습니다. 함수를 선언하는 유스 케이스가 void func(int const param)있지만 호출자에게는 영향을 미치지 않으며 호출하는 동안 함수에 의해 전달 된 값을 변경할 수 없다는 점에서 함수 자체에만 영향을 미치지 않습니다.

참조로 전달 : 예 : void func(int &param)이제 차이를 만듭니다. 방금 선언 한대로 func변경할 수 param있으며 모든 호출 사이트는 결과를 처리 할 준비가되어 있어야합니다. 선언을 void func(int const &param)변경하여 계약 을 변경하고 func이제는 변경할 수 없음을 보증합니다 param. 즉, 전달되는 것은 다시 나오는 것을 의미합니다. 다른 사람들이 지적했듯이 이것은 변경하고 싶지 않은 큰 객체를 저렴하게 전달하는 데 매우 유용합니다. 참조를 전달하는 것은 큰 객체를 값으로 전달하는 것보다 훨씬 저렴합니다.

포인터를지나 : 예, void func(int *param)그리고 void func(int const *param)이 두 호출 된 함수가 지금 확인하기 위해 필요로하는주의와 거의 동의어 자신의 기준 상대에있는 nullptr다른 계약 보증 보증한다 않는 한 func그것은을받지 않겠다고 nullptr에서 param.

그 주제에 대한 의견. 이와 같은 경우 정확성을 입증하는 것은 어려울 정도로 어렵습니다. 실수하기가 너무 쉽습니다. 따라서 기회를 놓치지 말고 항상에 대한 포인터 매개 변수를 확인하십시오 nullptr. 당신은 자신에게 고통과 고통을 저장하고 장기적으로 버그를 찾기 어렵다. 그리고 검사 비용은 먼지가 싸고 컴파일러에 내장 된 정적 분석이이를 관리 할 수있는 경우 옵티마이 저는이를 제거합니다. MSVC의 링크 타임 코드 생성 또는 GCC의 WOPR (제 생각에)을 켜면 소스 코드 모듈 경계를 넘는 함수 호출에서도 프로그램 전체에 적용 할 수 있습니다.

하루가 끝나면 위의 모든 내용이 항상 포인터에 대한 참조를 선호하는 매우 견고한 경우입니다. 그들은 모든 라운드에서 더 안전합니다.


3

양쪽에 int가있는 const는 상수 int에 대한 포인터를 만듭니다 .

const int *ptr=&i;

또는:

int const *ptr=&i;

constafter *int에 대한 지속적인 포인터를 만듭니다 .

int *const ptr=&i;

이 경우, 이것들 모두는 constant integer에 대한 포인터 이지만 이것들 중 어느 것도 상수 포인터가 아닙니다 :

 const int *ptr1=&i, *ptr2=&j;

이 경우 모두 상수 정수에 대한 포인터 이고 ptr2는 상수 정수에 대한 상수 포인터 입니다. 그러나 ptr1은 상수 포인터가 아닙니다.

int const *ptr1=&i, *const ptr2=&j;

3
  • 경우 const입니다 왼쪽*,이 값을 참조 (그것은 그건 문제가되지 않습니다 여부 const intint const)
  • 경우 const이다 오른쪽으로*, 그것은 포인터 자체를 의미
  • 동시에 둘 다 가능

중요한 점 : const int *p 당신이 말하는 가치가 일정하다는 것을 의미하지는 않습니다! . 그것은 당신이 그 포인터를 통해 그것을 바꿀 수 없다는 것을 의미합니다 (즉, $ * p = ...`를 지정할 수 없습니다). 값 자체는 다른 방식으로 변경 될 수 있습니다. 예 :

int x = 5;
const int *p = &x;
x = 6; //legal
printf("%d", *p) // prints 6
*p = 7; //error 

함수가 전달 된 인수를 실수로 변경할 수 없도록하기 위해 주로 함수 시그니처에 사용됩니다.


2

C에 대한 완전성을 위해 다른 설명을 따르고 C ++에 대해서는 확실하지 않습니다.

  • pp-포인터에 대한 포인터
  • p-포인터
  • 데이터-예에서 지적한 것 x
  • 굵은 체 -읽기 전용 변수

바늘

  • p 데이터- int *p;
  • p 데이터 -int const *p;
  • p 데이터-int * const p;
  • p 데이터 -int const * const p;

포인터를 가리키는 포인터

  1. pp p 데이터- int **pp;
  2. pp p 데이터-int ** const pp;
  3. pp p 데이터-int * const *pp;
  4. pp p 데이터 -int const **pp;
  5. pp p 데이터-int * const * const pp;
  6. pp p 데이터 -int const ** const pp;
  7. pp p 데이터 -int const * const *pp;
  8. pp p 데이터 -int const * const * const pp;
// Example 1
int x;
x = 10;
int *p = NULL;
p = &x;
int **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 2
int x;
x = 10;
int *p = NULL;
p = &x;
int ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 3
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 4
int const x = 10; // Definition must happen during declaration
int const * p = NULL;
p = &x;
int const **pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 5
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 6
int const x = 10; // Definition must happen during declaration
int const *p = NULL;
p = &x;
int const ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

// Example 7
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);

// Example 8
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

역 참조의 N 수준

계속 가십시오. 그러나 인류가 당신을 파문하기를 바랍니다.

int x = 10;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
int ****pppp = &ppp;

printf("%d \n", ****pppp);

0
  1. const int*-상수 int객체를 가리키는 포인터 .

포인터의 값을 변경할 수 있습니다. int포인터가 가리키는 객체 의 값을 변경할 수 없습니다 .


  1. const int * const-상수 int객체에 대한 상수 포인터 .

포인터의 값이나 int포인터가 가리키는 객체의 값을 변경할 수 없습니다 .


  1. int const *-상수 int객체를 가리키는 포인터 .

이 문장은 1과 같습니다 const int*.-포인터 값은 변경할 수 있지만 int포인터가 가리키는 개체 값은 변경할 수 없습니다 .


실제로, 네 번째 옵션이 있습니다.

  1. int * const- int객체에 대한 상수 포인터 .

포인터가 가리키는 객체의 값을 변경할 수 있지만 포인터 자체의 값은 변경할 수 없습니다. 포인터는 항상 같은 int객체를 가리 키지 만이 객체의이 값은 int변경 될 수 있습니다.


특정 유형의 C 또는 C ++ 구문을 결정하려면 David Anderson이 만든 시계 방향 / 나선 규칙을 사용할 수 있습니다 . 그러나 Ross J. Anderson이 만든 Anderson의 규칙 과 혼동하지 마십시오 .

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