Apa perbedaan antara char * const dan const char *?


279

Apa perbedaan antara:

char * const 

dan

const char *


8
Hal pertama di sebelah kiri "const" adalah apa yang konstan. Jika "const" adalah benda yang paling jauh ke kiri, maka hal pertama di sebelah kanannya adalah apa yang konstan.
Cupcake

4
Sebagai tip ramah, jangan pernah lupa bahwa cdecl adalah suatu hal.
Braden Best

Ada lagi char const * yang merupakan tipe pengembalian exception :: what ()
Zhang

Jawaban:


363

Perbedaannya adalah bahwa itu const char *adalah pointer ke const char, sedangkan char * constadalah pointer konstan ke a char.

Yang pertama, nilai yang ditunjuk tidak bisa diubah tetapi pointer bisa. Yang kedua, nilai yang ditunjukkan bisa berubah tetapi pointer tidak bisa (mirip dengan referensi).

Ada juga a

const char * const

yang merupakan pointer konstan ke char konstan (jadi tidak ada yang bisa diubah).

catatan:

Dua bentuk berikut ini setara:

const char *

dan

char const *

Alasan yang tepat untuk ini dijelaskan dalam standar C ++, tetapi penting untuk mencatat dan menghindari kebingungan. Saya tahu beberapa standar pengkodean yang lebih suka:

char const

lebih

const char

(dengan atau tanpa pointer) sehingga penempatan constelemen sama dengan pointer const.


6
Apakah bermanfaat untuk mencatat apa yang terjadi jika beberapa variabel ditentukan dalam deklarasi yang sama? Saya percaya const int *foo,*bar;akan mendeklarasikan keduanya foodan barmenjadi int const *, tetapi int const *foo, *barakan menyatakan foosebagai int const *dan barmenjadi int *. Saya pikir typedef int * intptr; const intptr foo,bar;akan mendeklarasikan kedua variabel menjadi int * const; Saya tidak tahu cara menggunakan deklarasi gabungan untuk membuat dua variabel dari tipe itu tanpa typedef.
supercat

1
@supercat I believe const int *foo,*bar; would declare both foo and bar to be int const *: Ya. but int const *foo, *bar would declare foo to be a int const * and bar to be int *: Tidak! Ini akan sama persis dengan kasus sebelumnya. (Lihat ideone.com/RsaB7n di mana Anda mendapatkan kesalahan yang sama untuk foo dan bar). I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: Iya. I don't know any way to use a combined declaration to create two variables of that type without a typedef: Nah, int *const foo, *const bar;. C deklarator sintaks ...
gx_

@ gx_: Jadi saya salah - ketidakpastian saya adalah mengapa saya menyarankan bahwa mungkin membantu untuk mengatakan apa aturannya. Apa yang akan int const *foo, *volatile bardilakukan bar? Buat keduanya constdan volatile? Saya rindu pemisahan bersih Pascal dari nama variabel yang dideklarasikan dan tipe mereka (pointer ke array pointer ke integer adalah var foo: ^Array[3..4] of ^Integer; `. Itu akan menjadi beberapa hal bersarang lucu bersarang di C, saya pikir.
supercat

3
@supercat (oh, C-hanya, maaf untuk link kode C ++, saya tiba di sini dari C ++ pertanyaan) Ini semua tentang sintaks C deklarasi , dengan ( "murni") jenis bagian diikuti oleh deklarator . Di int const *foo, *volatile barbagian tipe " " adalah int const(berhenti sebelum *) dan deklaratornya adalah *foo(ekspresi *fooakan menunjukkan suatu int const) dan *volatile bar; membaca kanan-ke-kiri (aturan yang baik untuk cv-kualifikasi ), fooadalah pointer ke sebuah const int, dan barmerupakan pointer yang mudah menguap ke sebuah const int (pointer itu sendiri tidak stabil, int menunjuk [diakses sebagai] const).
gx_

@supercat Dan sebagai untuk "pointer ke array dari pointer ke bilangan bulat" (Saya tidak tahu Pascal, tidak yakin tentang [3..4]sintaks, jadi mari kita array 10 elemen): int *(*foo)[10];. Ini mencerminkan penggunaannya (masa depan) sebagai ekspresi: *(*foo)[i](dengan ibilangan bulat dalam rentang [0, 10)yaitu [0, 9]) pertama akan dereferensi foountuk mendapatkan di array, kemudian mengakses elemen pada indeks i(karena postfix []mengikat lebih ketat daripada awalan *), kemudian dereferensi elemen ini, akhirnya menghasilkan int(lihat ideone.com/jgjIjR ). Tetapi typedefmembuatnya lebih mudah (lihat ideone.com/O3wb7d ).
gx_

102

Untuk menghindari kebingungan, selalu tambahkan kualifikasi const.

int       *      mutable_pointer_to_mutable_int;
int const *      mutable_pointer_to_constant_int;
int       *const constant_pointer_to_mutable_int;
int const *const constant_pointer_to_constant_int;

10
Mengapa? "Menghindari kebingungan" tidak menjelaskan apa yang membingungkan saya.
Andrew Weir

14
@ Andrew: Saya mengisyaratkan konsistensi dan karena itu mudah dibaca. Menulis semua jenis kualifikasi sehingga mereka memodifikasi apa yang ada di sebelah kiri mereka, selalu , itulah yang saya gunakan.
diapir

1
Sebenarnya ini adalah jawaban terbaik untuk masalah yang saya temukan di SO
Trap

8
Sebagai standar kode, saya jarang menemukan gaya ini dan karenanya saya tidak akan mengadopsinya. Namun sebagai alat pembelajaran, jawaban ini sangat membantu! (Jadi saya kira sayang sekali ini bukan gaya yang lebih umum.)
natevw

8
@Alla: ptidak berhubungan dengan jenis: (const int *const). Untuk lebih baik atau lebih buruk (lebih buruk jika Anda bertanya kepada saya) kualifikasi const, baik dalam C dan C ++, dimaksudkan sebagai postfix: cf const member function void foo(int a) const;. Kemungkinan untuk mendeklarasikan const intadalah pengecualian daripada aturan.
diapir

44

const selalu memodifikasi hal yang datang sebelum itu (di sebelah kiri itu), KECUALI ketika itu adalah hal pertama dalam deklarasi tipe, di mana ia memodifikasi hal yang datang setelah itu (di sebelah kanannya).

Jadi keduanya sama:

int const *i1;
const int *i2;

mereka mendefinisikan pointer ke a const int. Anda dapat mengubah tempat i1dan i2titik, tetapi Anda tidak dapat mengubah nilai yang mereka tunjukkan.

Ini:

int *const i3 = (int*) 0x12345678;

mendefinisikan constpointer ke integer dan menginisialisasi untuk menunjuk di lokasi memori 12345678. Anda dapat mengubah intnilai di alamat 12345678, tetapi Anda tidak dapat mengubah alamat yang i3menunjuk ke.



18

const char*adalah pointer ke karakter konstan
char* constadalah pointer konstan ke karakter
const char* constadalah pointer konstan ke karakter konstan


9

Rule of thumb: baca definisi dari kanan ke kiri!


const int *foo;

Berarti " foomenunjuk ( *) ke intyang tidak dapat mengubah ( const)".
Untuk programmer ini berarti "Saya tidak akan mengubah nilai apa yang foomenunjuk ke".

  • *foo = 123;atau foo[0] = 123;tidak valid.
  • foo = &bar; Diperbolehkan.

int *const foo;

Berarti " footidak dapat mengubah ( const) dan menunjuk ( *) ke sebuah int".
Untuk programmer ini berarti "Saya tidak akan mengubah alamat memori yang foomerujuk".

  • *foo = 123;atau foo[0] = 123;diizinkan.
  • foo = &bar; akan menjadi tidak valid.

const int *const foo;

Berarti " footidak dapat mengubah ( const) dan menunjuk ( *) ke intyang tidak dapat mengubah ( const)".
Bagi programmer, ini berarti "Saya tidak akan mengubah nilai dari foopoin apa , atau mengubah alamat yang foomerujuk".

  • *foo = 123;atau foo[0] = 123;tidak valid.
  • foo = &bar; akan menjadi tidak valid.

8
  1. const char * x Di sini X pada dasarnya adalah penunjuk karakter yang menunjuk ke nilai konstan

  2. char * const x merujuk ke penunjuk karakter yang konstan, tetapi lokasi yang ditunjuknya dapat berubah.

  3. const char * const x adalah kombinasi ke 1 dan 2, berarti itu adalah penunjuk karakter konstan yang menunjuk ke nilai konstan.

  4. const * char x akan menyebabkan kesalahan kompiler. itu tidak bisa dinyatakan.

  5. char const * x sama dengan poin 1.

aturan praktisnya adalah jika const adalah dengan nama var maka pointer akan konstan tetapi lokasi menunjuk dapat diubah , jika pointer akan menunjuk ke lokasi konstan dan pointer dapat menunjuk ke lokasi lain tetapi konten lokasi yang menunjuk tidak dapat diubah .


1
"char * const x merujuk ke penunjuk karakter yang konstan, tetapi lokasi yang ditunjuknya dapat berubah." Salah. Nilai di lokasi dapat diubah bukan lokasi itu sendiri.
PleaseHelp

3

Yang pertama adalah kesalahan sintaksis. Mungkin maksud Anda perbedaannya

const char * mychar

dan

char * const mychar

Dalam hal itu, yang pertama adalah pointer ke data yang tidak bisa berubah, dan yang kedua adalah pointer yang akan selalu menunjuk ke alamat yang sama.


3

Aturan praktis lainnya adalah untuk mengecek letak const :

  1. sebelum * => nilai yang disimpan konstan
  2. setelah * => pointer itu sendiri adalah konstan

3

Banyak jawaban memberikan teknik khusus, aturan praktis dll untuk memahami contoh khusus dari deklarasi variabel ini. Tetapi ada teknik umum untuk memahami pernyataan apa pun:

Searah Jarum Jam / Aturan Spiral

SEBUAH)

const char *a;

Sesuai aturan jarum jam / spiral aadalah penunjuk ke karakter yang konstan. Yang berarti karakter konstan tetapi pointer dapat berubah. yaitu a = "other string";baik-baik saja tetapi a[2] = 'c';akan gagal dikompilasi

B)

char * const a;

Sesuai aturan, aadalah pointer pointer ke karakter. yaitu Anda dapat melakukan a[2] = 'c';tetapi Anda tidak bisa melakukannyaa = "other string";


1
Juga dikenal sebagai aturan kanan-kiri (setidaknya itulah yang saya pelajari): jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html
Tomas Pruzina

(Akan jauh lebih baik jika esensi jawabannya tidak akan disembunyikan di balik tautan, dengan teks di sini bahkan tidak mengutip, atau setidaknya merujuk, ke salah satu spesifiknya, di luar generik "sesuai aturan".)
Sz.

@Sz. Apakah Anda memiliki kebingungan khusus di sini yang dapat saya hapus? Sebenarnya tidak banyak yang diketahui setelah mengetahui aturannya.
PnotNP

1

Saya kira maksudmu const char * dan char * const.

Yang pertama, const char *, adalah penunjuk ke karakter konstan. Pointer itu sendiri bisa berubah.

Yang kedua, char * const adalah pointer konstan ke karakter. Pointer tidak dapat berubah, karakter yang ditunjukkannya bisa.

Dan kemudian ada const char * const di mana pointer dan karakter tidak dapat berubah.


Dua pertama sebenarnya sama dan ketiga adalah kesalahan kompilator :)
workmad3

1

Berikut adalah penjelasan terperinci dengan kode

/*const char * p;
char * const p; 
const char * const p;*/ // these are the three conditions,

// const char *p;const char * const p; pointer value cannot be changed

// char * const p; pointer address cannot be changed

// const char * const p; both cannot be changed.

#include<stdio.h>

/*int main()
{
    const char * p; // value cannot be changed
    char z;
    //*p = 'c'; // this will not work
    p = &z;
    printf(" %c\n",*p);
    return 0;
}*/

/*int main()
{
    char * const p; // address cannot be changed
    char z;
    *p = 'c'; 
    //p = &z;   // this will not work
    printf(" %c\n",*p);
    return 0;
}*/



/*int main()
{
    const char * const p; // both address and value cannot be changed
    char z;
    *p = 'c'; // this will not work
    p = &z; // this will not work
    printf(" %c\n",*p);
    return 0;
}*/

@reese moore Terima kasih.
Megharaj

1
// Some more complex constant variable/pointer declaration.
// Observing cases when we get error and warning would help
// understanding it better.

int main(void)
{
  char ca1[10]= "aaaa"; // char array 1
  char ca2[10]= "bbbb"; // char array 2

  char *pca1= ca1;
  char *pca2= ca2;

  char const *ccs= pca1;
  char * const csc= pca2;
  ccs[1]='m';  // Bad - error: assignment of read-only location ‘*(ccs + 1u)’
  ccs= csc;    // Good

  csc[1]='n';  // Good
  csc= ccs;    // Bad - error: assignment of read-only variable ‘csc’

  char const **ccss= &ccs;     // Good
  char const **ccss1= &csc;    // Bad - warning: initialization from incompatible pointer type

  char * const *cscs= &csc;    // Good
  char * const *cscs1= &ccs;   // Bad - warning: initialization from incompatible pointer type

  char ** const cssc=   &pca1; // Good
  char ** const cssc1=  &ccs;  // Bad - warning: initialization from incompatible pointer type
  char ** const cssc2=  &csc;  // Bad - warning: initialization discards ‘const’
                               //                qualifier from pointer target type

  *ccss[1]= 'x'; // Bad - error: assignment of read-only location ‘**(ccss + 8u)’
  *ccss= ccs;    // Good
  *ccss= csc;    // Good
  ccss= ccss1;   // Good
  ccss= cscs;    // Bad - warning: assignment from incompatible pointer type

  *cscs[1]= 'y'; // Good
  *cscs= ccs;    // Bad - error: assignment of read-only location ‘*cscs’
  *cscs= csc;    // Bad - error: assignment of read-only location ‘*cscs’
  cscs= cscs1;   // Good
  cscs= cssc;    // Good

  *cssc[1]= 'z'; // Good
  *cssc= ccs;    // Bad - warning: assignment discards ‘const’
                 //                qualifier from pointer target type
  *cssc= csc;    // Good
  *cssc= pca2;   // Good
  cssc= ccss;    // Bad - error: assignment of read-only variable ‘cssc’
  cssc= cscs;    // Bad - error: assignment of read-only variable ‘cssc’
  cssc= cssc1;   // Bad - error: assignment of read-only variable ‘cssc’
}

1
  1. Pointer konstan : Pointer konstan dapat menunjuk hanya ke variabel tunggal dari masing-masing tipe data selama seluruh program. Kita dapat mengubah nilai variabel yang ditunjuk oleh pointer. Inisialisasi harus dilakukan selama waktu deklarasi itu sendiri.

Sintaksis:

datatype *const var;

char *const datang dalam kasus ini.

/*program to illustrate the behaviour of constant pointer */

#include<stdio.h>
int main(){
  int a=10;
  int *const ptr=&a;
  *ptr=100;/* we can change the value of object but we cannot point it to another variable.suppose another variable int b=20; and ptr=&b; gives you error*/
  printf("%d",*ptr);
  return 0;
}
  1. Pointer ke nilai const : Dalam pointer ini dapat menunjukkan sejumlah variabel dari masing-masing jenis tetapi kita tidak dapat mengubah nilai objek yang ditunjuk oleh pointer pada waktu tertentu.

Sintaksis:

const datatype *varatau datatype const *var

const char* datang dalam kasus ini.

/* program to illustrate the behavior of pointer to a constant*/

   #include<stdio.h>
   int main(){
       int a=10,b=20;
       int const *ptr=&a;
       printf("%d\n",*ptr);
       /*  *ptr=100 is not possible i.e we cannot change the value of the object pointed by the pointer*/
       ptr=&b;
       printf("%d",*ptr);
       /*we can point it to another object*/
       return 0;
    }

1

char * const dan const char *?

  1. Menunjuk ke nilai konstan

const char * p; // nilai tidak bisa diubah

  1. Pointer konstan ke nilai

char * const p; // alamat tidak bisa diubah

  1. Pointer konstan ke nilai konstan

const char * const p; // keduanya tidak bisa diubah.


1

The constpengubah diterapkan untuk jangka segera ke kiri nya. Satu-satunya pengecualian untuk ini adalah ketika tidak ada yang di sebelah kirinya, maka itu berlaku untuk apa yang ada di sebelah kanannya.

Ini semua adalah cara yang setara untuk mengatakan "pointer konstan ke konstanta char":

  • const char * const
  • const char const *
  • char const * const
  • char const const *

Apakah ini tergantung pada kompiler? gcc menghasilkan untuk "const char const *" dan "const const char *" dan "char const const *" hasil yang sama -> pointer dapat menunjuk ke lokasi lain.
cosinus0

1

Dua aturan

  1. If const is between char and *, it will affect the left one.
  2. If const is not between char and *, it will affect the nearest one.

misalnya

  1. char const *. This is a pointer points to a constant char.
  2. char * const. This is a constant pointer points to a char.

1

Saya ingin menunjukkan bahwa menggunakan int const *(atau const int *) bukan tentang pointer yang menunjuk ke suatu const intvariabel, tetapi bahwa variabel ini adalah constuntuk pointer spesifik ini.

Sebagai contoh:

int var = 10;
int const * _p = &var;

Kode di atas mengkompilasi dengan sangat baik. _pmenunjuk ke suatu constvariabel, meskipun varitu sendiri tidak konstan.


1

Saya ingat dari buku Czech tentang C: baca deklarasi yang Anda mulai dengan variabel dan ke kiri. Sehingga untuk

char * const a;

Anda dapat membaca sebagai: " aadalah variabel tipe pointer konstan ke char",

char const * a;

Anda dapat membaca sebagai: " aadalah pointer ke variabel konstan tipe char. Saya harap ini membantu.

Bonus:

const char * const a;

Anda akan membaca seperti apointer konstan ke variabel konstan tipe char.

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.