web-dev-qa-db-ja.com

Cの絶対値関数がconst入力を受け入れないのはなぜですか?

Cでは、絶対値関数(floatを受け入れる)のプロトタイプは次のとおりです。

 float fabsf( float );

このプロトタイプが次のように定数値を受け入れないのはなぜですか。

 float fabsf( float const );

fabsfは入力の値を変更しませんか?

入力を受け入れてfabsfを呼び出す関数がある場合、入力をconstとして指定しないように強制されますか?

この状況でconstの正確さを処理する適切な方法は何ですか?

23
user24205

編集

M.Mがコメントしたように、prototypesのパラメーターでは、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は、関数内でこれparameterを読み取り専用にします。

例えば:

_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を時々見るのですか? pointerがパラメーターとして定義されている場合に表示されます。

pointedの値を変更したくない場合は、constを追加する必要があります。しかし、正しい位置でそれをしてください!

_void effective(int const * pointer);

void futile(int * const pointer);

void possible_but_overly_restricted(int const * const pointer);
_
14
the busybee

Cは値渡しを使用します。関数のパラメーターの値は、指定した引数のコピーです。

Constとnon-const floatの両方をコピーしても問題ありません。結果はnon-const floatです。

これは割り当てに似ています。

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

実際、言語は、式の値がconstになることは決してないように指定しています。つまり、変数から値が読み取られた場合、変数がそうであったとしても、その値はconstではありません。

33
M.M

C言語は値渡しのセマンティクスを使用するため、渡したany引数は内部で変更できますが、渡した値に直接影響しません。

これは、呼び出し側から見ると、float fabsf( float );float fabsf( const float );は同じであることを意味します。したがって、パラメータconstを作成しても意味がありません。

doesconstを使用する意味があるのは、渡したパラメータがポインタである場合です。次に例を示します。

void print_string(char *str)

この関数は、その名前が示唆するものにもかかわらず、指定されたポインターを逆参照し、それが指すものを変更できます。つまり、str[0] = 'x'、呼び出し元の関数で表示可能な変更をもたらします。この関数が次のように定義されている場合:

void print_string(const char *str)

呼び出し側は、関数がstrが指す対象に変更を加えられないようにします。

8
dbush