char * constとconst char *の違いは何ですか?


279

違いは何ですか:

char * const 

そして

const char *


8
「const」の左側の最初のものは、定数です。「const」が最も左にあるものである場合、その右にある最初のものが定数です。
カップケーキ

4
フレンドリーなヒントとして、cdecl重要であることを忘れないでください。
ブレーデンベスト

例外の戻り値の型である別のchar const *があります:: what()
Zhang

回答:


363

違いはconst char *、へのポインタでありconst charchar * constへの定数ポインタcharです。

最初に、ポイントされている値は変更できませんが、ポインターは変更できます。2番目に、ポイントされている値は変更できますが、ポインターは変更できません(参照と同様)。

もあります

const char * const

これは定数charへの定数ポインタです(そのため、変更はできません)。

注意:

次の2つの形式は同等です。

const char *

そして

char const *

これの正確な理由はC ++標準に記載されていますが、混乱を避けて注意することが重要です。私は好むいくつかのコーディング標準を知っています:

char const

以上

const char

(ポインタの有無にかかわらず)、const要素の配置はポインタの場合と同じになりますconst


6
同じ宣言で複数の変数が指定された場合に何が起こるか注意する価値がありますか?私は信じているconst int *foo,*bar;の両方を宣言するだろうfoobarするint const *が、int const *foo, *bar宣言しfooするint const *barしますint *typedef int * intptr; const intptr foo,bar;両方の変数をと宣言すると思いますint * const。結合宣言を使用して、typedefなしでその型の2つの変数を作成する方法はわかりません。
スーパーキャット2013

1
@supercat I believe const int *foo,*bar; would declare both foo and bar to be int const *:はい。but int const *foo, *bar would declare foo to be a int const * and bar to be int *いいえ!前のケースとまったく同じです。(fooとbarの両方で同じエラーが発生するideone.com/RsaB7nを参照してください)。I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const: はい。I don't know any way to use a combined declaration to create two variables of that type without a typedef:まあ、int *const foo, *const bar;。C宣言子の構文...
gx_

@gx_:それで私は間違っていました-私の不確かさは、ルールが何であるかを言うことが役立つかもしれないと私が示唆した理由でした。何をするだろうint const *foo, *volatile barに行いますかbar?その両方作るconstvolatile?I宣言した変数名とそのタイプのミスパスカルの明確な分離(整数へのポインタの配列へのポインタのようになりますvar foo: ^Array[3..4] of ^Integer; `それはCでいくつかの面白いネストされた括弧付きのものになるだろう、私は思います。。
supercat

3
@supercat(ああ、Cのみ、C ++コードリンクで申し訳ありません。C++の質問からここに来ました)これは、C宣言構文に関するもので、(「純粋」)型の部分の後に宣言子が続きます。" int const *foo, *volatile bar"のタイプ部分はint const(の前に停止*)で、宣言子は*foo(式*fooはを示しますint const)と*volatile bar;です。読み取り右から左(のための良好なルールCV-修飾子fooへのポインタであるCONST INT、およびbarれる揮発性へのポインタのconst int型(ポインタ自体が揮発性である、尖ったINTはCONST [としてアクセス]れます)。
gx_

(約私はパスカルを知らない、わからない@supercatそして「整数へのポインタの配列へのポインタ」のよう[3..4]な構文、その者は、10個の要素の配列を取りましょう): int *(*foo)[10];。:それは表現としての(将来の)使用のミラー*(*foo)[i](とi範囲内の整数[0, 10)すなわち[0, 9])する最初の逆参照fooの配列で取得するために、そしてインデックスにある要素にアクセスするi(接尾ので、[]接頭辞よりもバインドがタイト*最後に、この要素を逆参照します、)を生成しますintideone.com/jgjIjRを参照)。しかしtypedef、それは簡単になります(ideone.com/O3wb7dを参照)。
gx_ 2013

102

混乱を避けるため、常に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
どうして?「混乱を避けるため」は私にとって混乱が何であるかを説明していません。
Andrew Weir

14
@Andrew:一貫性、ひいては読みやすさをほのめかしていた。すべての型修飾子を記述して、左側にあるものを常に変更するようにします。
diapir

1
実際、それは私がSOで見つけた主題に対する最良の答えです
トラップ14

8
コード標準として、私はこのスタイルに出くわすことはめったにないので、このスタイルを採用することはありません。ただし、学習ツールとして、この回答は非常に役に立ちました。(だから私はこれがあまり一般的なスタイルではないと思います。)
natevw

8
@Alla:pタイプに関連していません:(const int *const)。良くも悪くも(私に尋ねるとさらに悪いことですが)、CとC ++の両方のconst修飾子は、postfixを意味します:cf const member function void foo(int a) const;。宣言する可能性const intは、規則ではなく例外です。
ダイアピル2015

44

const 常にその前にあるもの(その左側にあるもの)を変更します。それが型宣言の最初のものである場合を除いて、その後にあるもの(その右側にあるもの)を変更します。

したがって、これら2つは同じです。

int const *i1;
const int *i2;

それらはへのポインタを定義しますconst int。場所i1i2ポイントは変更できますが、ポイントする値は変更できません。

この:

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

const整数へのポインタを定義し、メモリ位置12345678を指すように初期化intします。アドレス12345678で値を変更できますが、i3指すアドレスを変更することはできません。


22

const * char無効なCコードであり、無意味です。たぶん、あなたはa const char *とa char const *の違い、あるいはおそらくa とaの違いを尋ねるつもりでしconst char *char * const

以下も参照してください。



9

経験則:定義を右から左に読んでください!


const int *foo;

「は変更できないfoo*)を指す()」を意味します。 プログラマにとって、これは「ポイントするを変更しない」ことを意味しますintconst
foo

  • *foo = 123;またはfoo[0] = 123;無効になります。
  • foo = &bar; 許可されている。

int *const foo;

" fooは変更できない(const)ことを意味*し、()はint" を指します。
プログラマにとって、これは「参照するメモリアドレスを変更しない」ことをfoo意味します。

  • *foo = 123;またはfoo[0] = 123;許可されています。
  • foo = &bar; 無効になります。

const int *const foo;

手段「foo(変更できないconst)と点(*)にint(変更できませんconst)」。
プログラマにとって、これは「私が指すもののfooを変更したり、参照するアドレスを変更したりしないfoo」ことを意味します。

  • *foo = 123;またはfoo[0] = 123;無効になります。
  • foo = &bar; 無効になります。

8
  1. const char * xここで、Xは基本的に定数値を指す文字ポインターです

  2. char * const xは定数である文字ポインターを参照しますが、それが指している位置は変更される可能性があります。

  3. const char * const xは1と2の組み合わせであり、定数値を指す定数文字ポインターであることを意味します。

  4. const * char xはコンパイラエラーを引き起こします。宣言できません。

  5. char const * xはポイント1に等しい。

経験則として、constがvar nameを使用している場合、ポインターは一定ですが、ポインティング位置は変更できます。そうで、ポインターは一定のロケーションをポイントし、ポインターは別のロケーションをポイントできますが、ポインティングロケーションのコンテンツは変更できません


1
「char * const xは定数である文字ポインターを参照していますが、それが指している位置は変更される可能性があります。」違う。ロケーション自体の値ではなく、ロケーションの値を変更できます。
PleaseHelp

3

1つ目は構文エラーです。多分あなたは違いを意味した

const char * mychar

そして

char * const mychar

その場合、1つ目は変更できないデータへのポインターで、2つ目は常に同じアドレスを指すポインターです。


3

別の経験則は、constがどこにあるかを確認することです

  1. * => 保存される定数です
  2. 後* => ポインタ自体は定数です

3

多くの答えは、変数宣言のこの特定のインスタンスを理解するための特定のテクニック、経験則などを提供します。しかし、宣言を理解する一般的な手法があります。

時計回り/スパイラルルール

A)

const char *a;

時計回り/らせんのルールに従って、a定数である文字へのポインターです。つまり、文字は一定ですが、ポインタは変わる可能性があります。つまりa = "other string";、問題ありa[2] = 'c';ませんが、コンパイルに失敗します

B)

char * const a;

ルールに従って、a文字へのconstポインターです。つまり、あなたは行うことができますa[2] = 'c';が、行うことはできませんa = "other string";


1
右左ルールとも呼ばれます(少なくとも、この方法で学習しました):jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html
Tomas Pruzina

(回答のエッセンスがリンクの背後に隠されておらず、ここでのテキストが一般的な「ルールごと」を超えてその詳細のいずれも引用していない、または少なくとも言及していない場合は、はるかに良いでしょう。)
Sz。

@Sz。ここで明確にできる特定の混乱がありますか?ルールを知っていれば、それほど多くはありません。
PnotNP

1

const char *およびchar * constを意味していると思います。

最初のconst char *は、定数文字へのポインターです。ポインタ自体は変更可能です。

2番目のchar * constは、文字への定数ポインターです。ポインタは変更できません。ポインタが指す文字は変更できます。

そして、ポインタと文字が変更できないconst char * constがあります。


最初の2つは実際には同じで、3つ目はコンパイラエラーです:)
workmad3 '20年

1

ここにコード付きの詳細な説明があります

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

@リースムーアありがとうございます。
Megharaj 2013

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. 定数ポインター:定数ポインターは、プログラム全体で、それぞれのデータ型の単一の変数のみを指すことができます。ポインターが指す変数の値を変更できます。初期化は宣言自体の間に行われるべきです。

構文:

datatype *const var;

char *const この場合に該当します。

/*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. const値へのポインタ:この場合、ポインタはそれぞれの型の変数をいくつでも指すことができますが、その特定の時間にポインタが指すオブジェクトの値を変更することはできません。

構文:

const datatype *varまたは datatype const *var

const char* この場合に該当します。

/* 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およびconst char *?

  1. 定数値を指す

const char * p; //値は変更できません

  1. 値への定数ポインター

char * const p; //アドレスは変更できません

  1. 定数値への定数ポインタ

const char * const p; //両方を変更することはできません。


1

const修飾子は、そのすぐ左の用語に適用されます。これの唯一の例外は、左側に何もない場合で、そのすぐ右側にあるものに適用されます。

これらはすべて、「定数への定数ポインタ」と同等の言い方ですchar

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

コンパイラに依存していますか?gccは、 "const char const *"と "const const char *"と "char const const *"に対して同じ結果を生成します->ポインターが他の場所を指す可能性があります。
cosinus0 2017

1

2つのルール

  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.

例えば

  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 *(または const int *)を使用することは、const int変数を指すポインターではなく、この変数がconstこの特定のポインター用であることを指摘したいと思います。

例えば:

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

上記のコードは完全に正常にコンパイルされます。それ自体は定数ではありませんが_pconst変数を指しますvar


1

私はチェコのCに関する本から覚えています。変数から始めて左に行くという宣言を読んでください。だから

char * const a;

あなたは次のように読むことができます: " ais to variable of constant constant pointer to char"、

char const * a;

" aはchar型の定数変数へのポインタです。これが役立つことを願っています。

ボーナス:

const char * const a;

achar型の定数変数への定数ポインターをそのまま読み取ります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.