web-dev-qa-db-ja.com

char *とconst char *の違いは?

違いは何ですか

char* name

これは定数文字列リテラルを指します。

const char* name
146
Iceman

char*変更可能文字/文字列への変更可能ポインタです。

const char*不変文字/文字列への可変ポインタです。このポインタが指す場所の内容を変更することはできません。また、コンパイラはあなたがそうしようとしたときにエラーメッセージを出すように要求されます。同じ理由で、const char *からchar*への変換は非推奨です。

char* const不変ポインタです(他の場所を指すことはできません)しかしそれが指す場所の内容は可変.

const char* const不変文字/文字列への不変ポインタです。

335
ankit.karwasra
char *name

nameが指す文字、およびそれが指す文字も変更できます。

const char* name

nameが指す文字は変更できますが、それが指す文字は変更できません。
correct:ポインタは変更できますが、notnameが指す文字( https://msdn.Microsoft.com/ja-jp/library/vstudio/whkd4k6a(v = vs.100) ).aspx 、「例」を参照)この場合、const指定子はアスタリスクではなくcharに適用されます。

MSDNページおよび http://en.cppreference.com/w/cpp/language/declarations によると、*の前のconstはdecl指定子シーケンスの一部ですが、*の後のconst宣言子の一部です。
宣言指定子シーケンスの後に複数の宣言子を続けることができます。これがconst char * c1, c2c1const char *として、およびc2const charとして宣言している理由です。

編集:

コメントから、あなたの質問は、ポインタが文字列リテラルを指しているときの2つの宣言の違いについて尋ねているようです。

その場合、未定義の動作が発生する可能性があるので、nameが指す文字を変更しないでください。文字列リテラルは読み取り専用メモリ領域(実装定義)に割り当てることができます。ユーザープログラムでは変更しないでください。これを試みると、未定義の動作が発生します。

したがって、その場合(文字列リテラルを使用した場合)の唯一の違いは、2番目の宣言によってわずかな利点があることです。 2番目のケースで文字列リテラルを変更しようとすると、通常、コンパイラは警告を出します。

オンラインサンプル例:

#include <string.h>
int main()
{
    char *str1 = "string Literal";
    const char *str2 = "string Literal";
    char source[] = "Sample string";

    strcpy(str1,source);    //No warning or error, just Undefined Behavior
    strcpy(str2,source);    //Compiler issues a warning

    return 0;
}

出力:

cc1:警告はエラーとして扱われる
prog.c:関数 'main'内:
prog.c:9:エラー: 'strcpy'の引数1を渡すと、ポインタのターゲット型から修飾子が破棄されます

2番目のケースについてはコンパイラが警告しますが、最初のケースについては警告しません。

41
Alok Save
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)

constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error

constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok

// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";

lcharp[0] = 'X';      // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error

// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X';          // compile error
((char*)astr)[0] = 'X'; // ok
15
Afriza N. Arief

どちらの場合も、その文字列リテラルへのポインタがchar *またはconst char *として宣言されているかどうかにかかわらず、文字列リテラルを変更することはできません。

ただし、ポインターがconst char *の場合、ポインターの値を変更しようとするとコンパイラーは診断を行う必要がありますが、ポインターがchar *の場合はそうではありません。

9
caf

最初はあなたが望むなら実際に変えることができ、二番目はあなたができない。 constの正しさについてお読みください(違いについてのいくつかのNiceガイドがあります)。あなたがそれを指し示すことができないchar const * nameもあります。

2
chikuba

ケース1:

char *str = "Hello";
str[0] = 'M'  //No warning or error, just Undefined Behavior

上記のstrは、プログラムのバイナリイメージ内でハードコードされているリテラル値 "Hello"を指すようにstrを設定しています。

ケース2:

const char *str = "Hello";
str[0] = 'M'  //Compiler issues a warning

ケース3:

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
2
Mohit

実際、char* nameは定数へのポインタではなく、変数へのポインタです。あなたはこの他の質問について話しているかもしれません。

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

1
Jeff Wolski

問題はその違いは何ですか

char *name

これは定数文字列リテラルを指します。

const char *cname

すなわち与えられた

char *name = "foo";

そして

const char *cname = "foo";

2と両者の間に大きな違いはありませんが、両方とも正しいと見なすことができます。 Cコードは古くからあるため、文字列リテラルのタイプはchar[]ではなくconst char[]であり、引数を変更しない場合でも、char *ではなくconst char *を受け入れるより古いコードがたくさんあります。

一般的な2の主な違いは、*cnameまたはcname[n]const char型の左辺値に評価されるのに対して、*nameまたはname[n]は--- char型の左辺値に評価されることです---これは modifiable lvalues代入の対象が修正可能な左辺値ではない ;型charの左辺値への代入について警告を生成する必要はありません。

name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message

どちらの場合も、コンパイラはコンパイルを停止する必要はありません必要はありませんcname[0]への代入に対して警告を生成すれば十分です。結果のプログラムは正しいプログラムではありません。構文の振る舞いは未定義です。それはクラッシュするかもしれないし、さらに悪いことにはクラッシュしないかもしれず、そしてメモリ内の文字列リテラルを変更するかもしれません。

1
Antti Haapala

別の例を挙げてください。

    std::cout << typeid(2.3).name() << '\n'; // -----> prints "double" simply because
    //2.3 is a double
    //But the "double" returned by typeid(2.3).name() is indeed a 
    //const char * which consists of 'd','o','u','b','l','e'and'\0'.
    //Here's a simple proof to this:
    std::cout << typeid(typeid(2.3).name()).name() << '\n'; //prints: "const char *"
    const char* charptr
    charptr = typeid(2.3).name();
    std::cout << charptr[3]; // --------->  prints: "b"

(私はtypeinfoライブラリを使用しています: http://www.cplusplus.com/reference/typeinfo/type_info/name

    //Now let's do something more interesting:
    char* charptr2="hubble";
    strcpy(charptr, charptr2);  // --------> Oops! Sorry, this is not valid!

あなたはそれを実行して、自分にとって物事をよく見ることができます。

0
M-J