2012-04-10 27 views
125

次の宣言の違いは何ですか?私は(GCC 3.4で)プログラムをコンパイルし、それを実行した定数ポインタと定数値のポインタ

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

char * const a; 
const char * a; 

は違いを理解するために、私は、この小さなプログラムを書きました。出力はかなり差があります:

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


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

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

上記の例で、constキーワードの動作を説明してください。

+6

より完全な答えは以下ですが、私は 'const'が次のトークンにバインドすると思っています。だから 'char * const a'では' a'という変数自体が変更可能ではありません。 'const char * a'では、それは変更可能ではない文字にポイントされます。 – davmac

+0

私は、タイトルが "一定のポインタと定数値の間のポインタ"のように読むべきであると信じています。 – RBT

答えて

150
char * const a; 

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

const char * a; 

は、ポインティングされたデータをポインタaを使用して書き込むことができないことを意味します。 const_cast(C++)またはCスタイルのキャストを使用してこの場合constをキャストすると、未定義の動作が発生します。

+43

'const char * a **は**"指し示されたデータが定数で不変であることを意味しません。 'a'が書き込めないポインタだけです。指し示されたデータはsomeone-elseが書き込むことができます。例:https://gist.github.com/andyli/b4107c8910208fe54764 –

+3

@AndyLi指摘されたデータは他の人によって書き込まれることがあります。または、それは実際には一定にすることができます。文字列リテラル。 – EJP

9

最初のものは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. */ 
+0

説明をありがとうが、私はすでにこれらの結果に達しています(私の質問に貼り付けたコードに示されています)。私はconst演算子がどのように動作するのか、エンティティがどのようなエンティティであるかを解読する方法を説明する誰かを探しています。テストするマシン上でコードを実行する能力はありません。 – rahmu

59
char * const a; 

*a書き込み可能ですが、aはありません。つまり、に指定された値をaで変更できますが、a自体を変更することはできません。 aは、charへの定数ポインタであるです。

const char * a; 

a書き込み可能ですが、*aはありません。つまり、a(新しい場所を指す)を変更することはできますが、を指す値をaに変更することはできません。これは、この場合

char const * a; 

と同一であること

注、aconst charからポインタです。

63

複雑なタイプを解析するには、変数から開始し、左に移動し、外側にスパイラルします。 (変数名の右にあるので)気にする配列や関数がなければ、これは右から左に読む場合になります。

あなたはcharconstポインタ(*)でaを、持っているchar *const a;とだから。つまり、aが指している文字を変更することはできますが、aを別のものにすることはできません。あなたはconstあるcharへのポインタ(*)でbを、持っているconst char* b;と逆に

bは好きな文字を指すことができますが、*b = ...;を使ってその文字の値を変更することはできません。

もちろん、一度に両方の味の風味を持つこともできます:const char *const c;

+8

ファーストクラスの応答。答えを提供するだけでなく、これらのタイプの宣言を解析する方法を読者に教える。私はまた、宣言(例えば、int(*(* foo)(void))[3]を意味のある英語のテキストに変換するサイトとしてhttp://cdecl.org/を推奨します。 intの配列3へのポインタを返す ")。 – jarmod

17

char * const aconst char * aの違いを知ったことがあります。その定数ポインタまたは定数変数へのポインタの場合は、何度も混乱します。

どのように読むのですか?次の簡単な手順に従って、上位2つを識別します。

a

1で始まり右左

から読み宣言

char * const a; 

下に読む方法を見てみましょう。 aに隣接して、constがあります。

char * (const a);

---> so aは、constant(????)です。

2。今すぐお行けください。*

char (* (const a));

--->従ってaは、constantpointerから(????)です。

3。行くとそこにあるchar

(char (* (const a)));

--->aconstantpointercharacterに変数

a is constant pointer to character variable. 

を読み、それは容易ではないですか?

と似て2番目の宣言のために

const char * a; 

今再びa

1で始まります。aに隣接*

--->だから、aは(????)

2からpointerでもあります。さて、char

--->はそうapointercharacterある任意の意味をなさない

まあそこです!だから、pointercharacter

--->そうa(?????)

3からcharacterpointerでシャッフルします。今、あなたは持っているconstant

--->そうaがあるcharacterpointer

変数constantにしかし、あなたは宣言の意味を作ることができますが、それはより賢明な音を作ることができます。

a is pointer to constant character variable 
+0

物事をクリアする素晴らしい方法! :) – LordTitiKaka

+0

これはAATの答えのより冗長なバージョンではありませんか? – MestreLion

+1

ああ、私はそれを見ていませんでした。私の教授は私の工学の過程でこの方法を教えてくれました。初心者に役立つことを願っています。 –

13

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

  1. 何もポインタは、オブジェクトが指摘
  2. constのある
  3. のconstではないことはオブジェクトへのポインタと尖った両方
  4. のconstでのconstです。

これらの異なる可能性、次のようにCで表すことができる:

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

私はこれが

5

以上の可能な違いを示し希望は偉大な答えです。ここではこれを覚えておくための簡単な方法がある:あなたがして、ポインタがconstのある「CONST」と言う場合

ポインタ

です* aが値

は今です。 (つまりchar * const a;)

「const * a」と言う場合、値はconstです。 (すなわち、constのchar *;)

2

あなたが例えばhttp://www.lemoda.net/c/cdecl/

のように、CDECLユーティリティまたはそのオンライン版を使用することがあります。

void (* x)(int (*[])()); は、簡単な方法でお答えしようと declare x as pointer to function (array of pointer to function returning int) returning void

1

次のとおりです。

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. 

それはかつて一定のポインタポイントにそれが永遠であるいくつかのことを意味します。

ポインタaポイントのみb。あなたが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!. 
0
const char * a; 

これは、一定の文字へのポインタを述べています。 たとえば、 (この場合は「S」、)一定の文字に

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

ここaポイント。あなたはvalue.Butこの宣言は、それが本当にであるためにポイントする値を意味しないことに変更するaを使用することはできません定数は、aが関係している限り、値が定数であることを意味します。 bの値を直接bの値を変更することによって変更できますが、aポインタを介して間接的に値を変更することはできません。

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

char * const a=&b 

これはcharへの定数ポインタを述べています。 はbを指しますが、bの値を変更することができます。

:)

6

Iは、例を口頭で最初し、それを説明する:

ポインタオブジェクトがCONSTポインタまたはconstオブジェクト(あるいはその両方)へのポインタとして宣言することができる。

A constポインタは、最初に割り当てられたオブジェクトとは別のオブジェクトを指すように再割り当てすることはできませんが、そのオブジェクトを指し示すオブジェクト( "pointee"と呼ばれます)を変更するために使用できます。
参照変数は、constpointerの代わりの構文です。

constオブジェクトへのポインタは、同じタイプまたはコンバーチブルタイプの別のオブジェクトを指すように再割り当てできますが、オブジェクトの変更には使用できません。

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

例:

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 
} 

助けて幸せ!がんばろう!