Mengapa fungsi nilai absolut di C tidak menerima input const?

23

Di C, prototipe untuk fungsi nilai absolut (yang menerima float) adalah

 float fabsf( float );

Mengapa prototipe ini tidak menerima nilai konstan, seperti ini:

 float fabsf( float const );

fabsf tidak akan mengubah nilai input, kan?

Jika saya memiliki fungsi yang menerima input dan memanggil fabsf, apakah saya terpaksa menghindari menetapkan input sebagai const?

Apa cara yang tepat untuk menangani kebenaran const dalam situasi ini?

pengguna24205
sumber
26
constdi sini berlebihan, apa yang Anda bayangkan sedang terjadi?
MM
1
@ MM Saya berharap ini akan membuat kesalahan waktu kompilasi jika saya mencoba mengubah nilai input di dalam fungsi. Apakah ini salah?
user24205
16
Karena parameter di dalam fungsi adalah salinan lokal, menambahkan constsama sekali tidak berarti.
Lundin
1
" fabsf tidak akan mengubah nilai input, kan? " Bagaimana Anda bisa tahu? Parameter dilewatkan oleh nilai.
David Schwartz
Kode berikut adalah hukum C: float const x = -1.0; float y = fabsf(x);sehingga tampaknya bagi saya bahwa fabsf tidak menerima input const. Tidak ada cara untuk mengatakan "Anda bisa memberi saya floatnilai tetapi Anda tidak bisa melewati nilai const float." (Dan seperti yang kita lihat di jawaban, C tidak menyediakan cara untuk meminta agar input ke fungsi menjadi a float const.)
David K

Jawaban:

14

Edit

Sebagai MM berkomentar, pada parameter di prototipe tersebut constdiabaikan. Sumber yang diedit dari jawaban asli (lihat di bawah) menunjukkan ini:

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;
}

Tidak ada pesan kesalahan.

Ngomong-ngomong, aku akan membiarkan yang asli tetap di tempat dengan harapan itu bisa membantu.


Asli

Pada constparameter membuat parameter ini read-only di dalam fungsi.

Sebagai contoh:

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

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

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

Sumber ini tidak akan dikompilasi tanpa pesan kesalahan.

Fungsinya correct() akan membaca nilai yang diberikan, mengubah tandanya, dan mengembalikan nilai yang dinegasikan.

Fungsi erroneous()tampaknya melakukan hal yang sama secara efektif, kecuali bahwa ada tugas untuk parameter. Tetapi sebagai parameterconst ini tidak diperbolehkan.

Selanjutnya, fungsinya changer() akan berfungsi seperti keduanya sebelumnya, tetapi tidak memberikan kesalahan.

Mari kita lihat situs panggilan:

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

Variabel yang fdiberikan sebagai argumen akan disalin ke dalam parameter value. Itu tidak akan pernah berubah bahkan jikachanger() akan dipanggil.

Anda mungkin ingin melihat parameter sebagai semacam variabel lokal. Sebenarnya mereka sebagian besar ditangani seperti ini dalam kode mesin yang dihasilkan.


Jadi, mengapa constterkadang Anda melihat ? Anda melihatnya jika pointer didefinisikan sebagai parameter.

Saat Anda tidak ingin nilai yang ditunjukkan diubah, Anda perlu menambahkan const; tetapi lakukan pada posisi yang benar!

void effective(int const * pointer);

void futile(int * const pointer);

void possible_but_overly_restricted(int const * const pointer);
Sibuk
sumber
Pertanyaannya adalah tentang prototipe, prototipe float fabsf( float const );tidak ada hubungannya dengan implementasi fungsi (yang tidak harus mengulangi const), pada kenyataannya constdiabaikan seluruhnya dalam prototipe
MM
2
Dapatkah const masuk dalam definisi fungsi tanpa masuk prototipe?
user24205
3
@ user24205 ya itu bisa
Daniel Jour
33

C menggunakan pass by value. Nilai untuk parameter fungsi adalah salinan argumen yang Anda berikan.

Tidak masalah untuk menyalin float const dan non-const, dan hasilnya adalah float non-const.

Ini mirip dengan penugasan:

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

Bahkan, bahasa menetapkan bahwa nilai ekspresi tidak pernah bisa const, yaitu ketika nilai dibaca dari suatu variabel, nilai itu tidak constbahkan jika variabel itu.

MM
sumber
8

Karena bahasa C menggunakan semantik nilai lewat, argumen apa pun yang Anda berikan, sementara itu dapat dimodifikasi secara internal, tidak secara langsung memengaruhi nilai yang Anda masukkan.

Ini berarti dari sudut pandang penelepon, float fabsf( float );dan float fabsf( const float );sama. Jadi tidak ada gunanya membuat parameterconst .

Di mana ia tidak masuk akal untuk digunakan constadalah jika parameter Anda lulus dalam adalah pointer, misalnya:

void print_string(char *str)

Fungsi ini, terlepas dari apa yang disarankan oleh namanya, dapat mengubah pointer yang diberikan dan memodifikasi apa yang ditunjukkannya, yaitu str[0] = 'x', untuk menghasilkan perubahan yang dapat dilihat oleh fungsi panggilan. Jika fungsi ini didefinisikan seperti ini:

void print_string(const char *str)

Penelepon dipastikan bahwa fungsi tidak dapat melakukan modifikasi apa pun ke strpoin.

dbush
sumber
"Penelepon memastikan bahwa fungsi tidak dapat melakukan modifikasi ..." itu tidak benar. Fungsi tahu alamat data dan oleh karena itu dapat memodifikasi, dengan, misalnya: ((char*)str)[0] = 'f'. The const ... *dalam daftar argumen karena itu hanya "deklarasi niat".
oromoiluig
5

Untuk menambahkan perspektif pengacara bahasa:

Untuk dua jenis fungsi agar kompatibel, keduanya harus menentukan jenis pengembalian yang kompatibel. Selain itu, daftar tipe parameter, jika keduanya ada, harus menyetujui jumlah parameter dan penggunaan terminator elipsis; parameter yang sesuai harus memiliki tipe yang kompatibel . [..] Dalam penentuan kompatibilitas tipe dan tipe komposit, [..] setiap parameter yang dideklarasikan dengan tipe terkualifikasi dianggap memiliki versi tanpa pengecualian dari tipe yang dideklarasikan. .

N1570 6.7.6.3/15

Itu berarti keduanya kompatibel:

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

Oleh karena itu Anda dapat menulis prototipe dengan atau tanpa const(yang berarti tanpa lebih masuk akal; kurang untuk mengetik / membaca) dan dapat menambahkan constdefinisi fungsi jika Anda ingin menghindari secara tidak sengaja memodifikasi parameter (nilai panggilan - disalin!) Di dalam fungsi tubuh.

Daniel Jour
sumber