C ++ 및 C의 함수 매개 변수로서 'const int'대 'int const'


116

치다:

int testfunc1 (const int a)
{
  return a;
}

int testfunc2 (int const a)
{
  return a;
}

이 두 기능은 모든 측면에서 동일합니까 아니면 차이점이 있습니까?

C 언어에 대한 답변에 관심이 있지만 C ++ 언어에 흥미로운 점이 있다면 저도 알고 싶습니다.


지금 C에 const 키워드가 있습니까? 예전에는 없었지만 C 99 표준에 익숙하지 않습니다.
Onorio Catenacci

8
당신은 그럴 필요가 없습니다. C90이면 충분합니다. 하지만 원래 K & R C에는 없었습니다.
Mark Baker

3
C89 및 ANSI의 키워드입니다. Kerningham과 Richie 시대에 그것이 키워드 였는지 모르겠습니다.
Nils Pipenbrinck

7
이 사이트는 "C gibberish"를 영어로 번역합니다. cdecl.org
Motti

5
나는 "영어 횡설수설에 C의 횡설수설"라고하지만, 여전히 좋은 :) 것
코스

답변:


175

const TT const동일하다. 포인터 유형을 사용하면 더 복잡해집니다.

  1. const char* 상수에 대한 포인터 char
  2. char const* 상수에 대한 포인터 char
  3. char* const (변경 가능)에 대한 상수 포인터입니다. char

즉, (1)과 (2)는 동일합니다. 포인터를 만드는 유일한 방법은 (pointee가 아닌) 접미사 const를 사용하는 것 const입니다.

이것이 많은 사람들이 항상 const유형의 오른쪽에 배치하는 것을 선호하는 이유입니다 ( "East const"스타일). 유형에 상대적인 위치를 일관되고 기억하기 쉽게 만듭니다 (일화 적으로도 초보자에게 가르치기 쉽게 만드는 것 같습니다. ).


2
C는 다음과 같이 const를 갖습니다. static const char foo [] = "foo"; foo를 변경하지 않는 것이 좋습니다.
James Antill

4
K & R C에는 const가 없었습니다. C90 (및 C99)은 그렇습니다. C ++에 비해 약간 제한적이지만 유용합니다.
Mark Baker

참고 문헌에서도 마찬가지입니까?

1
@Ken 예, 동일합니다.
Konrad Rudolph

1
@ étale-cohomology 좋은 지적이 추가되었습니다. 계속 거기 있었어야 했어.
Konrad Rudolph

339

트릭은 선언을 거꾸로 읽는 것입니다 (오른쪽에서 왼쪽으로) :

const int a = 1; // read as "a is an integer which is constant"
int const a = 1; // read as "a is a constant integer"

둘 다 같은 것입니다. 따라서:

a = 2; // Can't do because a is constant

역방향 읽기 트릭은 다음과 같은 더 복잡한 선언을 다룰 때 특히 유용합니다.

const char *s;      // read as "s is a pointer to a char that is constant"
char c;
char *const t = &c; // read as "t is a constant pointer to a char"

*s = 'A'; // Can't do because the char is constant
s++;      // Can do because the pointer isn't constant
*t = 'A'; // Can do because the char isn't constant
t++;      // Can't do because the pointer is constant

5
"char const * u"는 어떻습니까? "상수 문자에 대한 포인터"또는 "문자에 대한 상수 포인터"라고 읽습니까? 모호한 것 같습니다. 표준은 전자를 말합니다. 그러나 이것을 알아 내기 위해서는 우선 순위와 연관성 규칙을 고려해야합니다.
Panayiotis Karabassis

5
@PanayiotisKarabassis All은 자리를 바꾸지 않고 형용사 체인으로 취급되어야합니다. char const *, 왼쪽에서 오른쪽으로 읽는 것은 "pointer, const, char"입니다. const char에 대한 포인터입니다. "상수 포인터"라고 말하면 "상수"형용사가 포인터 위에 있습니다. 따라서이 경우 형용사 목록은 실제로 "const, pointer, char"이어야합니다. 하지만 당신 말이 맞습니다.이 트릭에는 모호성이 있습니다. 그것은 결정적인 "규칙"이 아닌 "속임수"입니다.
Ates Goral

5
배열, 함수, 포인터 및 함수 포인터의 와일드 조합을 선언하면 역방향 읽기가 더 이상 작동하지 않습니다 (슬프게도). 그러나 이러한 지저분한 선언은 나선형 패턴으로 읽을 수 있습니다 . 다른 사람들은 Go를 발명했습니다.
Martin JH 2014 년

@Martin JH : typedef를 사용하여 분리 할 수 ​​없습니까? 그리고 / 또는 간접 참조를 제거하기 위해 참조를 사용합니까?
Peter Mortensen

14

다른 점이 없다. 둘 다 "a"를 변경할 수없는 정수로 선언합니다.

차이점이 나타나기 시작하는 곳은 포인터를 사용할 때입니다.

둘 다 :

const int *a
int const *a

"a"를 변경되지 않는 정수에 대한 포인터로 선언하십시오. "a"는 할당 할 수 있지만 "* a"는 할당 할 수 없습니다.

int * const a

"a"를 정수에 대한 상수 포인터로 선언합니다. "* a"는 할당 할 수 있지만 "a"는 할당 할 수 없습니다.

const int * const a

"a"를 상수 정수에 대한 상수 포인터로 선언합니다. "a"또는 "* a"는 할당 할 수 없습니다.

static int one = 1;

int testfunc3 (const int *a)
{
  *a = 1; /* Error */
  a = &one;
  return *a;
}

int testfunc4 (int * const a)
{
  *a = 1;
  a = &one; /* Error */
  return *a;
}

int testfunc5 (const int * const a)
{
  *a = 1;   /* Error */
  a = &one; /* Error */
  return *a;
}

마지막 예는 가장 간단한 설명입니다.
2019 년

7

Prakash는 포인터 케이스에 대한 약간의 설명이 순서가있을 수 있지만 선언이 동일하다는 사실이 정확합니다.

"const int * p"는 해당 포인터를 통해 int가 변경되는 것을 허용하지 않는 int에 대한 포인터입니다. "int * const p"는 다른 int를 가리 키도록 변경할 수없는 int에 대한 포인터입니다.

https://isocpp.org/wiki/faq/const-correctness#const-ptr-vs-ptr-const를 참조 하세요 .


앵커 ( "faq-18.5.)가 끊어졌습니다. 어느 것을 참조해야합니까 ("const "및"* "가있는 여러 개가 있음)?
Peter Mortensen

@PeterMortensen : 예, 링크 부패. 감사. 링크를 업데이트했습니다.
Fred Larson

5

const int동일 int const같은 일반적 C. 모든 스칼라 유형 참인 스칼라 함수 매개 변수를 선언하고, constC의 호출 - 바이 - 값 의미 변수의 변경이 클로징 기능에 국부적 것을 의미하기 때문에, 필요하지 않다.


4

이것은 직접적인 대답이 아니라 관련 팁입니다. 일을 똑바로 유지하기 위해 저는 항상 " const외부에 놓기"대류를 사용합니다 . 여기서 "외부"는 맨 왼쪽 또는 맨 오른쪽을 의미합니다. 이렇게하면 혼동이 없습니다. const는 가장 가까운 것 (유형 또는 *)에 적용됩니다. 예 :



int * const foo = ...; // Pointer cannot change, pointed to value can change
const int * bar = ...; // Pointer can change, pointed to value cannot change
int * baz = ...; // Pointer can change, pointed to value can change
const int * const qux = ...; // Pointer cannot change, pointed to value cannot change

6
당신은 "const는 그것의 나머지를 const로 만든다"라는 규칙을 사용하는 것이 더 나을 것입니다. 예를 들어 "int * const foo"는 포인터가 왼쪽에 있기 때문에 포인터를 "const"로 만듭니다. 그러나 두 번째 줄 "int const * bar"를 작성하면 int const가됩니다. "int const * const * qux"는 둘 중 하나가 한 번 남아 있기 때문에 int와 포인터를 모두 const로 만듭니다.
Mecki

4

그것들은 동일하지만 C ++에서는 항상 오른쪽에 const를 사용해야하는 좋은 이유가 있습니다. const 멤버 함수 는 다음과 같이 선언 해야 하므로 모든 곳에서 일관성 이 있습니다.

int getInt() const;

그것은 변화 this에서 함수 포인터 Foo * constFoo const * const. 여기를 보아라.


3
이것은 완전히 다른 종류의 const입니다.
Justin Meiners

1
이것이 완전히 다른 이유는 무엇입니까? 반대표를받을만큼 충분히 다릅니다.
Nick Westgate

1
예, 질문은 "const int"와 "int const"의 차이에 관한 것입니다. 귀하의 대답은 그와 관련이 없습니다.
Justin Meiners

1
나는 그들이 같다고 말했다. 그러나 수락 및 최고 투표 답변은 포인터 유형에 대한 추가 정보도 제공합니다. 당신도 그들도 반대 투표 했습니까?
Nick Westgate 2016

3

예, 그들은 단지 동일합니다 int

그리고 다른 int*


5
(const int *) 및 (int const *)는 동일하며 (int * const)와 다릅니다.
James Antill

3

이 경우에는 동일하다고 생각하지만 다음은 순서가 중요한 예입니다.

const int* cantChangeTheData;
int* const cantChangeTheAddress;

2
실제로,하지만 int const *는 첫 번째와 동일하므로 int와 const의 순서는 중요하지 않습니다. 단지 *와 const의 순서 일뿐입니다.
Mark Baker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.