C의 절대 값 함수가 const 입력을 허용하지 않는 이유는 무엇입니까?


23

C에서, 절대 값 함수 (float를 받아들이는)의 프로토 타입은

 float fabsf( float );

이 프로토 타입이 다음과 같은 상수 값을 허용하지 않는 이유는 무엇입니까?

 float fabsf( float const );

fabsf는 입력 값을 변경하지 않습니까?

입력을 받아들이고 fabsf를 ​​호출하는 함수가 있으면 입력을 const로 지정하지 않아야합니까?

이 상황에서 const 정확성을 처리하는 적절한 방법은 무엇입니까?


26
const여기에 여분이 있는데, 무슨 일이 일어나고 있습니까?
MM

1
@ MM 함수 내부의 입력 값을 변경하려고하면 컴파일 시간 오류가 발생할 것으로 예상합니다. 이것이 맞지 않습니까?
user24205

16
함수 내부의 매개 변수는 로컬 복사본이므로 추가 const는 전혀 의미가 없습니다.
Lundin

1
" fabsf는 입력 값을 변경하지 않습니까? "어떻게 말할 수 있습니까? 매개 변수는 값으로 전달됩니다.
David Schwartz

다음 코드는 합법적 인 C입니다 : float const x = -1.0; float y = fabsf(x);그래서 const 입력을 받아들이 fabsf 것 같습니다 . " float값으로 나에게 전달할 수 있지만을 (를) 통과 할 수는 없습니다 "라고 말할 방법이 없습니다 const float. (그리고 답에서 볼 수 있듯이 C는 함수에 대한 입력을 요구할 수있는 방법을 제공하지 않습니다 float const.)
David K

답변:


14

편집하다

MM이 언급했듯이 프로토 타입 의 매개 변수에 const대해서는 무시됩니다. 원본 답변의 수정 된 출처 (아래 참조)는 다음과 같습니다.

float correct(float const value);

float erroneous(float const value);

float changer(float value);

float correct(float value) {
  return -value;
}

float erroneous(float value) {
  value = -value;
  return value;
}

float changer(float value) {
    value = -value;
    return value;
}

오류 메시지가 없습니다.

어쨌든, 나는 그것이 도움이되기를 바라면서 원본을 그대로 두겠습니다.


기발한

const매개 변수에서이 만드는 매개 변수 읽기 전용 함수 내에서합니다.

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

float correct(float const value) {
  return -value;
}

float erroneous(float const value) {
  value = -value;
  return value;
}

float changer(float value) {
  value = -value;
  return value;
}

이 소스는 오류 메시지없이 컴파일되지 않습니다.

함수 correct()는 주어진 값을 읽고 부호를 변경하고 부정 된 값을 반환합니다.

erroneous()매개 변수에 할당이 있다는 점을 제외하고는 함수 가 효과적으로 동일한 것으로 보입니다. 그러나 매개 변수는 const허용되지 않습니다.

다음으로 함수 changer()는 이전과 같이 작동하지만 오류는 없습니다.

콜 사이트를 보자 :

float f = 3.14159;
float g = correct(f); // or erroneous(f) or changer(f)

변수 f인수로 제공이됩니다 복사 매개 변수로 value. changer()호출 되더라도 변경되지 않습니다 .

매개 변수를 일종의 로컬 변수로 보려고 할 수 있습니다. 실제로 이들은 생성 된 머신 코드에서 대부분 이와 같이 처리됩니다.


const가끔 봅니까? 포인터 가 매개 변수로 정의 된 경우이를 볼 수 있습니다 .

지정된 값 을 변경 하지 않으려면 추가해야합니다 const. 그러나 올바른 위치에서 수행하십시오!

void effective(int const * pointer);

void futile(int * const pointer);

void possible_but_overly_restricted(int const * const pointer);

문제는 프로토 타입이, 비록 프로토 타입에 관한 float fabsf( float const );합니다 (반복하지 않는 기능 구현과 아무 상관이 없습니다 const가 사실), const프로토 타입에 완전히 무시된다
MM

2
프로토 타입을 사용하지 않고도 const를 함수 정의에 사용할 수 있습니까?
user24205

3
@ user24205 그렇습니다
Daniel Jour

33

C는 값으로 전달을 사용합니다. 함수의 매개 변수 값은 사용자가 제공 한 인수의 사본입니다.

const와 non-const float를 모두 복사해도 괜찮으며 결과는 non-const float입니다.

과제와 비슷합니다 :

const float f = 5.5f;
float g = f;   // OK

실제로이 언어는 식의 값을 절대로 사용할 수 없도록 지정합니다. const즉, 변수에서 값을 읽을 때 해당 값은 const변수가 아니더라도 해당 값이 아닙니다 .


8

C 언어에서 사용하는 값의 의미를 통과하기 때문에, 어떤 내부적으로 수정 될 수 있지만 당신이 그것을에 전달한다는 주장은, 직접이 전달 값에 영향을주지 않습니다.

이 그 발신자의 관점에서 수단 float fabsf( float );float fabsf( const float );동일합니다. 따라서 매개 변수를 만들 필요는 없습니다 const.

그것은 어디 않습니다 메이크업 센스를 사용하는 const당신이 전달 매개 변수, 예를 들면 포인터 인 경우 :

void print_string(char *str)

이 함수는 이름에서 제안한 내용에도 불구하고 주어진 포인터를 역 참조하고 그 점을 수정 str[0] = 'x'하여 호출 함수가 볼 수있는 변경을 초래할 수 있습니다. 이 함수가 다음과 같이 정의 된 경우 :

void print_string(const char *str)

호출자는 함수가 지시하는 내용을 수정할 수 없도록 보장 str됩니다.


"호출자는 함수가 어떤 수정도 수행 할 수 없음을 보장합니다 ..."는 사실이 아닙니다. 이 함수는 데이터의 주소를 알고 있으므로 다음과 같이 수정할 수 있습니다 ((char*)str)[0] = 'f'. const ... *인수 목록에 따라서 만 "의도의 선언"입니다.
oromoiluig

5

언어 변호사 관점을 추가하려면 다음을 수행하십시오.

두 가지 기능 유형이 호환 되려면 둘 다 호환 가능한 반환 유형을 지정해야합니다. 또한, 매개 변수 유형 목록은 둘 다 존재하는 경우 매개 변수의 수와 줄임표 종결자를 사용하는 데 동의해야합니다. 해당 매개 변수는 호환 가능한 유형을 가져야합니다 . [..] 형식 호환성 및 복합 형식의 결정에서 [..] 정규화 된 형식으로 선언 된매개 변수는 선언 된 형식의 정규화되지 않은 버전을 갖는 것으로 간주됩니다 .

N1570 6.7.6.3/15

이는이 두 가지가 호환됨을 의미합니다.

void foo(int const);
void foo(int);

따라서 함수 내에서 (복사-값으로 호출!) 매개 변수를 실수로 수정하지 않으려는 경우 프로토 타입을 작성하거나 사용하지 않고 const(더 의미가없고 의미가 적고 입력 / 읽기가 적음) const함수 정의에 추가 할 수 있습니다 . 신체.

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