Char * const ve const char * arasındaki fark nedir?


279

Arasındaki fark nedir:

char * const 

ve

const char *


8
"Sabit" in solundaki ilk şey sabit olan şeydir. Eğer "const" en soldaki şeyse, sağındaki ilk şey sabit olan şeydir.
Cupcake

4
Dostça bir ipucu olarak, cdecl'in bir şey olduğunu asla unutmayın .
Braden Best

İstisna dönüş türü olan başka bir char const * var :: what ()
Zhang

Yanıtlar:


363

Aradaki fark, const char *a işaretçisi const chariken char * const, a işaretçisi sabittir char.

Birincisi, işaret edilen değer değiştirilemez, ancak işaretçi değiştirilebilir. İkincisi, işaret edilen değer değişebilir ancak işaretçi değişemez (bir referansa benzer).

Ayrıca bir

const char * const

ki bu sabit bir karaktere ait sabit bir göstergedir (böylece onun hakkında hiçbir şey değiştirilemez).

Not:

Aşağıdaki iki form eşdeğerdir:

const char *

ve

char const *

Bunun kesin nedeni C ++ standardında açıklanmıştır, ancak karışıklığı not etmek ve önlemek önemlidir. Tercih ettiğim birkaç kodlama standardını biliyorum:

char const

bitmiş

const char

(işaretçi olsun veya olmasın), böylece constöğenin yerleşimi işaretçi ile aynı olur const.


6
Aynı bildirimde birden çok değişken belirtilirse ne olacağını not etmekte fayda var mı? İnanıyorum const int *foo,*bar;hem ilan edeceğini foove barolmaya int const *, ama int const *foo, *barilan edeceğini foobir olmak int const *ve barolmayı int *. Bence typedef int * intptr; const intptr foo,bar;her iki değişkeni de int * const; Ben typedef olmadan bu tür iki değişken oluşturmak için birleşik bir bildirimi kullanmak için herhangi bir yol bilmiyorum.
supercat

1
@supercat I believe const int *foo,*bar; would declare both foo and bar to be int const *: Evet. but int const *foo, *bar would declare foo to be a int const * and bar to be int *: Hayır! Bir önceki durumla tamamen aynı olurdu. ( Hem foo hem de bar için aynı hatayı aldığınız ideone.com/RsaB7n adresine bakın ). I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: Evet. I don't know any way to use a combined declaration to create two variables of that type without a typedef: Şey int *const foo, *const bar;,. C declarator sözdizimi ...
gx_

@gx_: Yani yanılmışım - belirsizliğim, kuralların ne olduğunu söylemenin yararlı olabileceğini öne sürmemdi. Ne int const *foo, *volatile baryapmalı bar? Hem olun constve volatile? Pascal'ın beyan edilen değişken isimlerini ve türlerini temiz bir şekilde özlüyorum (tamsayılara işaret eden bir dizi işaretçi bir var foo: ^Array[3..4] of ^Integer
işarettir

3
@supercat (oh, sadece C, C ++ kod bağlantısı için özür dilerim, burada bir C ++ sorusundan aldım) Her şey C bildirimi sözdizimi ile ilgili , bir ("saf") tip parçası ve ardından bir bildirici ile ilgili . " int const *foo, *volatile bar" Türünde bölüm int const(önce durur *) ve bildiriciler *foo( *fooifade bir anlamına gelir int const) ve *volatile bar; okuma sağdan sola (için iyi bir kural ev elemeleri ), foobir bir işaretçidir const int ve bara, uçucu bir işaretçi const int (kendisi uçucu işaretçi, sivri int const [olarak erişilebilir] edilir).
gx_

Ve "tamsayılar için işaretçiler dizisi bir işaretçi" gelince @supercat (Ben Pascal bilmiyorum emin hakkında [3..4]sözdizimi, bu yüzden 10 elemanlardan oluşan bir dizi atalım): int *(*foo)[10];. (Gelecekte) kullanımını bir ifade olarak yansıtır: *(*foo)[i]( yani i, aralıktaki bir tamsayı ile ), önce diziye ulaşmak için dereference olur, daha sonra dizindeki öğeye erişir (çünkü postfix önekten daha sıkı bağlanır ), sonra bu öğeyi dereference bir elde (bakınız ideone.com/jgjIjR ). Ancak bunu kolaylaştırır (bkz. İdeone.com/O3wb7d ). [0, 10)[0, 9]fooi[]*inttypedef
gx_

102

Karışıklığı önlemek için her zaman sabit niteleyiciyi ekleyin .

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
Neden? "Karışıklıktan kaçınmak" benim için karışıklığın ne olduğunu açıklamaz.
Andrew Weir

14
@Andrew: Tutarlılığa ve dolayısıyla okunabilirliğe işaret ediyordum. Her tür niteleyiciyi yazmak için sollarında olanı her zaman değiştirirler .
diapir

1
Aslında
Tuzak

8
Bir kod standardı olarak, nadiren bu stille karşılaştım ve bu yüzden benimsemek olası değil. Ancak bir öğrenme aracı olarak, bu cevap çok yardımcı oldu! (Bu yüzden çok kötü sanırım bu daha yaygın bir stil değil.)
natevw

8
@Alla: ptipine ilgili değildir: (const int *const). Daha iyi veya daha kötü için (bana sorarsanız daha da kötüsü) hem C hem de C ++ 'da const niteleyicisinin postfix olması gerekir: cf const member işlevi void foo(int a) const;. Beyan etme olasılığı const intkuraldan çok istisnadır.
diapir

44

const her zaman ondan önce (solunda) gelen şeyi değiştirir, bir tür bildirimindeki ilk şey hariçtir, sonra gelen şeyi (sağında) değiştirir.

Yani bu ikisi aynı:

int const *i1;
const int *i2;

a işaretçileri tanımlarlar const int. Yeri i1ve i2noktaları değiştirebilirsiniz , ancak işaret ettikleri değeri değiştiremezsiniz.

Bu:

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

constbir tamsayıya bir işaretçi tanımlar ve 12345678 bellek konumunu işaret edecek şekilde başlatır. 12345678 intadresindeki değeri değiştirebilirsiniz , ancak i3işaret eden adresi değiştiremezsiniz .



18

const char*sabit bir karakterin
char* constişaretçisidir sabit bir karakterin işaretçisidir sabit bir karakterin
const char* constsabit işaretçisidir


9

Temel kural: tanımı sağdan sola okuyun!


const int *foo;

Means " foonoktaları ( *bir kadar) intdeğiştiremezsiniz ki ( const)".
Programcı için bu " neyi işaret ettiğinin değerini değiştirmeyeceğim" anlamına gelir foo.

  • *foo = 123;veya foo[0] = 123;geçersiz olur.
  • foo = &bar; izin verilir.

int *const foo;

" fooDeğişemez ( const) ve puan ( *) int" anlamına gelir ".
Programcı için bu aracı "Ben değişmeyecek bellek adresinifoo belirtir".

  • *foo = 123;veya foo[0] = 123;izin verilir.
  • foo = &bar; geçersiz olur.

const int *const foo;

" fooDeğiştirilemez ( const) ve noktaları ( *) intdeğiştirilemeyen ( const) anlamına gelir".
Programcı için bu aracı "Ben değişmeyecek değeri ne fooişaret ettiği, ne de değişecek adresifoo belirtir".

  • *foo = 123;veya foo[0] = 123;geçersiz olur.
  • foo = &bar; geçersiz olur.

8
  1. const char * x Burada X temel olarak sabit bir değere işaret eden bir karakter işaretçisi

  2. char * const x sabit olan karakter işaretçisine karşılık gelir, ancak işaret ettiği konum değiştirilebilir.

  3. const char * const x , 1 ve 2 ile birleşimidir, sabit değere işaret eden sabit bir karakter işaretçisi anlamına gelir.

  4. const * char x derleyici hatasına neden olur. ilan edilemez.

  5. char const * x , nokta 1'e eşittir.

temel kural const var adındaysa işaretçi sabit olacaktır, ancak işaretçi konumu değiştirilebilir , başka bir işaretçi sabit bir konumu gösterecektir ve işaretçi başka bir konumu gösterebilir ancak işaretleme konumu içeriği değiştirilemez .


1
"char * const x sabit olan karakter işaretçisini ifade eder, ancak işaret ettiği konum değiştirilebilir." Yanlış. Konumdaki değer konumun kendisi değil değiştirilebilir.
Lütfen

3

Birincisi bir sözdizimi hatasıdır. Belki arasındaki farkı kastediyorsun

const char * mychar

ve

char * const mychar

Bu durumda, birincisi değiştirilemeyen verilere bir işaretçi, ikincisi ise her zaman aynı adrese işaret edecek bir göstericidir.


3

Başka bir başparmak kuralı, const'un nerede olduğunu kontrol etmektir :

  1. * => depolanan değer sabit olmadan önce
  2. * => işaretçisinin kendisi sabit olduğunda

3

Pek çok cevap, değişken bildirimin bu özel örneğini anlamak için özel teknikler, temel kurallar vb. Ancak herhangi bir beyanı anlamak için genel bir teknik vardır:

Saat Yönünde / Spiral Kural

A)

const char *a;

Saat yönünde / spiral kuralına göre asabit karakter işaretçisi. Bu, karakterin sabit olduğu ancak işaretçinin değişebileceği anlamına gelir. yani a = "other string";iyi ama a[2] = 'c';derleme başarısız olacak

B)

char * const a;

Kural gereği, abir karakterin sabit göstergesidir. yani yapabilirsin a[2] = 'c';ama yapamazsına = "other string";


1
Sağ-sol kural olarak da bilinir (en azından ben bunu öğrendim): jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html
Tomas Pruzina

(Cevabın özü bir bağlantının arkasına gizlenmezse, buradaki metin, genel bir "kural uyarınca" nın ötesinde herhangi bir spesifikasyondan alıntı yapmıyor veya en azından kendi özelliklerinden bahsetmiyorsa çok daha iyi olurdu.)
sz.

@Sz. Burada temizleyebileceğim özel bir karışıklığınız var mı? Kuralı bildikten sonra gerçekten fazla bir şey yok.
PnotNP

1

Sanırım const char * ve char * const demek istiyorsun.

Birincisi, const char *, sabit bir karakterin işaretçisidir. İşaretçinin kendisi değiştirilebilir.

İkinci char * const, bir karakterin sabit bir göstergesidir. İşaretçi değişemez, işaret ettiği karakter.

Ve sonra işaretçi ve karakterin değiştirilemeyeceği const char * const vardır.


İlk
ikiniz

1

İşte kod ile ayrıntılı bir açıklama

/*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 Teşekkür ederim.
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. Sabit işaretçi : Sabit işaretçi , tüm program sırasında yalnızca ilgili veri türünün tek bir değişkenini işaret edebilir. İşaretçinin işaret ettiği değişkenin değerini değiştirebiliriz. Başlatma, bildirimin kendisi sırasında yapılmalıdır.

Sözdizimi:

datatype *const var;

char *const bu davaya giriyor.

/*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. Sabit değere işaretçi: Burada bir işaretçi, ilgili türdeki herhangi bir sayıda değişkeni gösterebilir, ancak belirli bir zamanda işaretçinin işaret ettiği nesnenin değerini değiştiremeyiz.

Sözdizimi:

const datatype *varveya datatype const *var

const char* bu davaya giriyor.

/* 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 ve const char *?

  1. Sabit bir değere işaret etme

const char * p; // değer değiştirilemez

  1. Bir değere sabit işaretçi

char * const p; // adres değiştirilemez

  1. Sabit bir değere sabit işaretçi

const char * const p; // her ikisi de değiştirilemez.


1

constModifiye edici olarak hemen solundaki terime uygulanır. Bunun tek istisnası, solunda hiçbir şey olmadığında, hemen sağında olanlara uygulanır.

Bunların hepsi "bir sabite sabit işaretçi" demenin eşdeğer yollarıdır char:

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

Derleyici bağımlı mı? "const char const *" ve "const const char *" ve "char const const *" için gcc üretmek aynı sonucu -> işaretçi başka bir yere işaret edebilir.
cosinus0

1

İki kural

  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.

Örneğin

  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

int const *(Veya const int *) kullanmanın bir const intdeğişkene işaret eden bir işaretçi ile ilgili olmadığını , ancak bu değişkenin constbu belirli işaretçi için olduğunu belirtmek isterim .

Örneğin:

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

Yukarıdaki kod mükemmel şekilde derlenir. kendisi sabit olmasa da _pbir constdeğişkeni vargösterir.


1

Çek kitabından C ile ilgili hatırlıyorum: değişkenle başladığınız beyanı okuyup sola dönüyorum. İçin böylece

char * const a;

şu şekilde okuyabilirsiniz: " adeğişmez sabit tip değişkenidir char",

char const * a;

şöyle okuyabilirsiniz: " achar türünün sabit değişkeninin bir göstergesidir. Umarım bu yardımcı olur.

Bonus:

const char * const a;

Gibi okuyacak atürü char sabit değişkene sabit göstericidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.