'const int' vs. 'int const' sebagai parameter fungsi di C ++ dan C


116

Mempertimbangkan:

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

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

Apakah kedua fungsi ini sama di setiap aspek atau ada perbedaan?

Saya tertarik dengan jawaban untuk bahasa C, tetapi jika ada sesuatu yang menarik dalam bahasa C ++, saya ingin mengetahuinya juga.


Apakah sekarang ada kata kunci const di C? Dulu tidak ada tapi saya tidak begitu akrab dengan standar C 99.
— Onorio Catenacci

8
Anda tidak perlu seperti itu. C90 sudah cukup. Itu tidak ada di K&R C asli.
— Mark Baker

3
Ini adalah kata kunci di C89 dan ANSI. Saya tidak tahu apakah itu kata kunci di masa Kerningham dan Richie.
— Nils Pipenbrinck

7
Situs ini menerjemahkan "C omong kosong" ke bahasa Inggris cdecl.org
— Motti

5
Saya akan mengatakan "C omong kosong ke bahasa Inggris omong kosong", tapi masih bagus :)
— Kos

Jawaban:


175

const Tdan T constidentik. Dengan tipe pointer, ini menjadi lebih rumit:

  1. const char* adalah penunjuk ke sebuah konstanta char
  2. char const* adalah penunjuk ke sebuah konstanta char
  3. char* const adalah penunjuk konstan ke (bisa berubah) char

Dengan kata lain, (1) dan (2) identik. Satu-satunya cara untuk membuat pointer (daripada pointee) constadalah dengan menggunakan sufiks- const.

Inilah sebabnya mengapa banyak orang lebih suka untuk selalu menempatkan constdi sisi kanan jenis (gaya "East const"): ini membuat lokasinya relatif terhadap jenis yang konsisten dan mudah diingat (juga secara anekdot tampaknya membuatnya lebih mudah untuk diajarkan kepada pemula ).


2
C memang memiliki const, diberikan: static const char foo [] = "foo"; Anda lebih baik tidak mengubah foo.
— James Antill

4
K&R C tidak memiliki const; C90 (dan C99) tidak. Ini agak terbatas dibandingkan dengan C ++, tetapi ini berguna.
— Mark Baker

apakah ini juga berlaku untuk referensi?
— Ken

1
@Ken Ya, sama saja.
— Konrad Rudolph

1
@ étale-cohomology Poin yang bagus, ditambahkan. Seharusnya sudah ada selama ini.
— Konrad Rudolph

339

Triknya adalah membaca deklarasi secara terbalik (kanan-ke-kiri):

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

Keduanya adalah hal yang sama. Karena itu:

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

Trik membaca mundur sangat berguna ketika Anda berurusan dengan deklarasi yang lebih kompleks seperti:

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
bagaimana dengan "char const * u"? Apakah ini membaca "Penunjuk ke karakter konstan" atau "penunjuk yang konstan ke karakter"? Sepertinya ambigu. Standar mengatakan yang pertama, tetapi untuk mengetahuinya, Anda harus mempertimbangkan aturan presedensi dan asosiatif.
— Panayiotis Karabassis

5
@PanayiotisKarabassis Semua harus diperlakukan sebagai rangkaian kata sifat, tanpa bertukar tempat. char const *, dibaca dari kiri ke kanan adalah: "pointer, const, char". Ini adalah penunjuk ke const char. Saat Anda mengatakan "penunjuk yang konstan", kata sifat "konstan" ada di penunjuk. Jadi, untuk kasus ini, daftar kata sifat Anda seharusnya benar-benar: "const, pointer, char". Tapi Anda benar, ada ambiguitas dalam trik ini. Ini benar-benar sebuah "tipuan", lebih dari sekedar "aturan" yang pasti.
— Ates Goral

5
Saat Anda mendeklarasikan kombinasi liar dari larik, fungsi, penunjuk, dan penunjuk fungsi, pembacaan mundur tidak berfungsi lagi (sayangnya). Namun, Anda dapat membaca deklarasi yang berantakan ini dalam pola spiral . Yang lain begitu frustrasi dengan mereka sehingga mereka menemukan Go.
— Martin JH

@ Martin JH: Tidak bisakah mereka dipecah melalui typedefs? Dan / atau menggunakan referensi untuk menghilangkan tipuan?
— Peter Mortensen

14

Tidak ada perbedaan. Keduanya menyatakan "a" sebagai bilangan bulat yang tidak dapat diubah.

Tempat di mana perbedaan mulai muncul adalah saat Anda menggunakan petunjuk.

Keduanya:

const int *a
int const *a

mendeklarasikan "a" sebagai penunjuk ke integer yang tidak berubah. "a" bisa ditetapkan ke, tapi "* a" tidak bisa.

int * const a

menyatakan "a" sebagai penunjuk konstan ke integer. "* a" bisa ditetapkan ke, tapi "a" tidak bisa.

const int * const a

menyatakan "a" sebagai penunjuk konstan ke bilangan bulat konstan. Baik "a" maupun "* a" tidak dapat ditetapkan ke.

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

Contoh terakhir adalah penjelasan paling sederhana, bagus!
— exru

7

Prakash benar bahwa deklarasinya sama, meskipun sedikit lebih banyak penjelasan tentang kasus penunjuk mungkin sesuai.

"const int * p" adalah penunjuk ke int yang tidak mengizinkan int untuk diubah melalui penunjuk itu. "int * const p" adalah penunjuk ke int yang tidak bisa diubah untuk menunjuk ke int lain.

Lihat https://isocpp.org/wiki/faq/const-correctness#const-ptr-vs-ptr-const .


Jangkar ("faq-18.5.) Rusak. Yang mana yang harus dirujuk (ada beberapa dengan" const "dan" * ")?
— Peter Mortensen

@PeterMortensen: Ya, link rot. Terima kasih. Saya memperbarui tautan.
— Fred Larson

5

const intidentik dengan int const, seperti halnya dengan semua jenis skalar di C. Secara umum, mendeklarasikan parameter fungsi skalar sebagai consttidak diperlukan, karena semantik panggilan-demi-nilai C berarti bahwa setiap perubahan pada variabel bersifat lokal ke fungsi penutupnya.


4

Ini bukan jawaban langsung tetapi tip terkait. Untuk menjaga hal-hal tetap lurus, saya selalu menggunakan konveksi "letakkan constdi luar", sedangkan "di luar" yang saya maksud adalah paling kiri atau paling kanan. Dengan cara itu tidak ada kebingungan - const berlaku untuk hal terdekat (baik tipe atau *). Misalnya,



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
Anda mungkin lebih baik menggunakan aturan "const membuat const apa pun yang tersisa". Misalnya "int * const foo" menjadikan pointer "const", karena pointer diserahkan ke sana. Namun, Anda akan menulis baris kedua "int const * bar", membuat int const, karena dibiarkan begitu saja. "int const * const * qux", membuat keduanya, int dan pointer const, karena salah satunya diserahkan ke sana.
— Mecki

4

Keduanya sama, tetapi di C ++ ada alasan bagus untuk selalu menggunakan const di sebelah kanan. Anda akan konsisten di mana-mana karena fungsi anggota const harus dideklarasikan dengan cara ini:

int getInt() const;

Ini mengubah thispenunjuk dalam fungsi dari Foo * constmenjadi Foo const * const. Lihat disini.


3
Ini adalah jenis const yang sama sekali berbeda.
— Justin Meiners

1
Mengapa ini sangat berbeda? Cukup berbeda untuk mendapatkan suara negatif.
— Nick Westgate

1
Ya, pertanyaannya adalah tentang perbedaan antara "const int" dan "int const", jawaban Anda tidak ada hubungannya dengan itu.
— Justin Meiners

1
Saya mengatakan mereka sama. Namun jawaban yang diterima dan paling banyak dipilih juga memberikan info tambahan tentang jenis penunjuk. Apakah Anda juga tidak menyukai itu?
— Nick Westgate

3

Ya, mereka sama saja int

dan berbeda untuk int*


5
(const int *) dan (int const *) sama, hanya berbeda dari (int * const).
— James Antill

3

Saya pikir dalam hal ini mereka sama, tetapi berikut adalah contoh di mana urutan itu penting:

const int* cantChangeTheData;
int* const cantChangeTheAddress;

2
Memang, tapi int const * sama dengan yang pertama, jadi urutan int dan const tidak menjadi masalah, hanya urutan * dan konstanta yang penting.
— Mark Baker
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.