web-dev-qa-db-ja.com

定数ポインターと定数値のポインター

次の宣言の違いは何ですか?

char * const a;
const char * a;

違いを理解するために、この小さなプログラムを書きました。

#include <stdio.h>
#include <stdlib.h>


int main (int argc, char **argv)
{
    char a = 'x';
    char b = 'y';

    char * const pc1 = &a;
    const char * pc2 = &a;

    printf ("Before\n");
    printf ("pc1=%p\n", pc1);
    printf ("*pc1=%c\n", *pc1);
    printf ("pc2=%p\n", pc2);
    printf ("*pc2=%c\n", *pc2);

    *pc1 = b;
/*     pc1 = &b; */

/*     *pc2 = b; */
    pc2 = &b;

    printf ("\n\n");

    printf ("After\n");
    printf ("pc1=%p\n", pc1);
    printf ("*pc1=%c\n", *pc1);
    printf ("pc2=%p\n", pc2);
    printf ("*pc2=%c\n", *pc2);

    return EXIT_SUCCESS;
}

プログラムを(gcc 3.4で)コンパイルして実行しました。出力は、違いをかなり強調しています。

Before
pc1=ffbfd7e7
*pc1=x
pc2=ffbfd7e7
*pc2=x


After
pc1=ffbfd7e7
*pc1=y
pc2=ffbfd7e6
*pc2=x

ただし、答えを得るには小さなプログラムを作成する必要がありました。マシンから離れている場合(たとえば、インタビューで)、質問に答えることができません。

上記の例をコメントして、誰かがconstキーワードがどのように動作するか説明してください。

140
rahmu
char * const a;

は、ポインターは定数で不変ですが、ポイントされたデータはそうではないことを意味します。
データ自体は定数ではないため、この場合、const_cast(C++)またはcスタイルのキャストを使用して、constnessをキャストできます。

const char * a;

は、ポインタaを使用して、ポイントされたデータに書き込むことができないことを意味します。この場合、const_cast(C++)またはcスタイルのキャストを使用してconstnessをキャストすると、ndefined Behaviorが発生します。

169
Alok Save

複雑な型を解析するには、変数から開始し、左に進み、外側に向かって螺旋を描きます。心配する配列や関数がない場合(変数名の右側にあるため)、これは右から左に読み取る場合になります。

したがって、char *const a;にはaがあります。これはconstへのcharポインター(*)です。つまり、aが指しているcharを変更できますが、aが異なるものを指すようにすることはできません。

逆にconst char* b;を使用すると、bを持つcharへのポインター(*)であるconstがあります。 bを任意のcharに向けることができますが、*b = ...;を使用してそのcharの値を変更することはできません。

もちろん、一度に両方のconst-nessを同時に使用することもできます:const char *const c;

87
AAT
char * const a;

*aは書き込み可能ですが、aは書き込みできません。つまり、aによって値pointedを変更できますが、a自体は変更できません。 acharへの定数ポインターです。

const char * a; 

aは書き込み可能ですが、*aは書き込みできません。言い換えると、aを変更(新しい場所を指す)ことができますが、値pointedaによって変更することはできません。

これは次と同じであることに注意してください

char const * a;

この場合、aconst charへのポインターです。

60
John Bode

これで、char * const aconst char * aの違いがわかりました。定数ポインターまたは定数変数へのポインターである場合、多くの場合混乱します。

読み方は?以下の簡単な手順に従って、上の2つを識別します。

以下の宣言の読み方を見てみましょう

char * const a;

右から左に読む

ここで、aで始まり、

1 aの隣にconstがあります。

char * (const a);

--->したがって、aconstant(????)です。

2。今すぐあなたは*を取得します

char (* (const a));

--->したがって、aconstantpointerから(????)です。

3。一緒に行くとcharがあります

(char (* (const a)));

---> aconstantpointerからcharacter変数です

a is constant pointer to character variable. 

読みにくいですか?

同様に2番目の宣言について

const char * a;

もう一度aから始めて、

1 aに隣接して*があります

--->したがって、aは(????)へのpointerです

2。今charがあります

--->したがって、apointercharacterです。

まあそれは意味をなさない!!! pointercharacterをシャッフルする

--->したがって、acharacterpointerから(?????)です

3。これでconstantができました

--->したがってacharacterpointerからconstant変数です

しかし、宣言の意味を理解することはできますが、より賢明に聞こえるようにしましょう。

a is pointer to constant character variable
22
Sagar Sakre

違いを理解する最も簡単な方法は、さまざまな可能性を考えることです。考慮する2つのオブジェクトがあります。ポインターと指すオブジェクトです(この場合、「a」はポインターの名前、指すオブジェクトは名前のないchar型です)。可能性は次のとおりです。

  1. 何もconstではありません
  2. ポインターはconstです
  3. 指しているオブジェクトはconstです
  4. ポインタとオブジェクトへのポインタの両方がconstです。

これらの異なる可能性は、次のようにCで表現できます。

  1. char * a;
  2. char * const a;
  3. const char * a;
  4. const char * const a;

これが可能な違いを説明することを願っています

15
John Vincent

最初はcharへの定数ポインターであり、2番目は定数charへのポインターです。コード内のすべてのケースに触れたわけではありません。

char * const pc1 = &a; /* You can't make pc1 point to anything else */
const char * pc2 = &a; /* You can't dereference pc2 to write. */

*pc1 = 'c' /* Legal. */
*pc2 = 'c' /* Illegal. */

pc1 = &b; /* Illegal, pc1 is a constant pointer. */
pc2 = &b; /* Legal, pc2 itself is not constant. */
12
cnicutar

上記は素晴らしい答えです。これを覚える簡単な方法を次に示します。

aはポインターです

* aは値です

「const a」と言うと、ポインターはconstです。 (つまり、char * const a;)

「const * a」と言うと、値はconstです。 (つまりconst char * a;)

5
jack

最初に口頭で説明し、次に例を示します。

ポインターオブジェクトは、「const」ポインターまたは「const」オブジェクトへのポインター(またはその両方)として宣言できます。

A -const pointerは、最初に割り当てられたオブジェクトとは異なるオブジェクトを指すように再割り当てすることはできませんが、それが指すオブジェクト(「ポインティ」と呼ばれる)を変更するために使用できます。
参照変数は、したがって、「constpointers」の代替構文です。

一方、a const objectへのポインターは、同じ型または変換可能な型の別のオブジェクトを指すように再割り当てできますが、オブジェクトの変更には使用できません。

A constオブジェクトへのconstポインタも宣言することができ、指示先を変更したり、別のオブジェクトを指すように再割り当てしたりすることはできません。

例:

void Foo( int * ptr,
         int const * ptrToConst,
         int * const constPtr,
         int const * const constPtrToConst ) 
{ 
    *ptr = 0; // OK: modifies the "pointee" data 
    ptr = 0; // OK: modifies the pointer 

    *ptrToConst = 0; // Error! Cannot modify the "pointee" data
     ptrToConst = 0; // OK: modifies the pointer 

    *constPtr = 0; // OK: modifies the "pointee" data 
    constPtr = 0; // Error! Cannot modify the pointer 

    *constPtrToConst = 0; // Error! Cannot modify the "pointee" data 
    constPtrToConst = 0; // Error! Cannot modify the pointer 
}

お力になれて、嬉しいです!がんばろう!

5
Barel

https://cdecl.org/ のようなcdeclユーティリティまたはそのオンラインバージョンを使用できます。

例えば:

void (* x)(int (*[])());declare x as pointer to function (array of pointer to function returning int) returning voidです

2
Zinovy Nis

簡単な方法で答えようとする:

char * const a;  => a is (const) constant (*) pointer of type char {L <- R}. =>( Constant Pointer )
const char * a;  => a is (*) pointer to char constant             {L <- R}. =>( Pointer to Constant)

定数ポインター:

ポインターは定数です!!。つまり、保持しているアドレスは変更できません。読み取り専用メモリに保存されます。

もっと理解するために、ポインターのアドレスを変更してみましょう。

char * const a = &b; 
char c;
a = &c; // illegal , you can't change the address. `a` is const at L-value, so can't change. `a` is read-only variable.

定数ポインターが何かを指すと、それは永遠に続くことを意味します。

ポインターabのみを指します。

ただし、bの値は変更できます。例:

char b='a';
char * const a =&b;

printf("\n print a  : [%c]\n",*a);
*a = 'c';
printf("\n now print a  : [%c]\n",*a);

定数へのポインター:

ポインターが指す値は変更できません。

const char *a;
char b = 'b';
const char * a =&b;
char c;
a=&c; //legal

*a = 'c'; // illegal , *a is pointer to constant can't change!.
1
B_San
const char * a;

これは、定数文字へのポインターを示します。例えば.

char b='s';
const char *a = &b;

ここでaは定数char( 's'、この場合)を指します。aを使用してその値を変更することはできません。ただし、この宣言は、それが指す値が constant、それは、aに関する限り、値が定数であることを意味します。 bの値を変更すると、bの値を直接変更できますが、aポインターを介して間接的に値を変更することはできません。

*a='t'; //INVALID b='t' ; //VALID

char * const a=&b

これは、charへの定数ポインターを示します。 abのみを指すように制限しますが、bの値を変更できます。

それが役に立てば幸い!!! :)

0
user4291320