web-dev-qa-db-ja.com

C ++は文字列定数から 'char *'への非推奨の変換

private char str[256];を持つクラスがあります

それのために、明示的なコンストラクタがあります:

explicit myClass(const char *func)
{
    strcpy(str,func);
}

私はそれを次のように呼びます:

myClass obj("example");

これをコンパイルすると、次の警告が表示されます。

文字列定数から 'char *'への非推奨の変換

なんでこんなことが起こっているの?

132
mkamthan

これは、次のような状況がある場合に表示されるエラーメッセージです。

char* pointer_to_nonconst = "string literal";

どうして?さて、CとC++は文字列リテラルのタイプが異なります。 Cでは型はcharの配列であり、C++ではconstant charの配列です。いずれの場合でも、文字列リテラルの文字を変更することは許可されていないため、C++のconstは実際には制限ではなく、タイプセーフです。通常、const char*からchar*への変換は、安全上の理由から明示的なキャストなしでは不可能です。ただし、Cとの後方互換性のために、C++言語では、char*に文字列リテラルを割り当てることができ、この変換が廃止されることを警告しています。

そのため、constの正確性のために、プログラムの1つ以上のconstsが欠落している場所があります。ただし、このような非推奨の変換は行わないため、あなたが示したコードは問題ではありません。警告は他の場所から来たに違いありません。

121
sellibitze

警告:

文字列定数から 'char *'への非推奨の変換

あなたがどこかに(あなたが投稿したコードではなく)何かをしているので、与えられます:

void foo(char* str);
foo("hello");

問題は、(タイプconst char[]の)文字列リテラルをchar*に変換しようとしていることです。

const char[]const char*に変換できます。これは、配列がポインターに減衰するためですが、あなたがしていることは、可変を定数にすることです。

この変換はおそらくC互換性のために許可されており、前述の警告が表示されるだけです。

回答番号2 by fnieto-Fernando Nieto この警告は、投稿したコードではなく、コードのどこかで行われているため、明確かつ正確に説明されています。

void foo(char* str);
foo("hello");

ただし、コードに警告を付けないようにする場合は、コードにそれぞれ変更を加えるだけです。

void foo(char* str);
foo((char *)"hello");

つまり、単にstring定数を(char *)にキャストします。

83
sactiw

3つの解決策があります。

解決策1:

const char *x = "foo bar";

解決策2:

char *x = (char *)"foo bar";

解決策3:

char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");

配列はすでに定数ポインターであるため、ポインターの代わりに配列を使用することもできます。

32
anilbey

実際、文字列定数リテラルはconst char *またはchar *ではなく、char []です。非常に奇妙ですが、c ++仕様に書き留められています。変更すると、コンパイラがコードセグメントに格納する可能性があるため、動作は未定義です。

3
dan ionescu

たぶんあなたはこれを試すことができます:

void foo(const char* str) 
{
    // Do something
}

foo("Hello")

わたしにはできる

1
Alen Lee

この問題を解決するには、コードの先頭のどこかにこのマクロを追加します。または、<iostream>に追加します、hehe。

 #define C_TEXT( text ) ((char*)std::string( text ).c_str())
1
TWOPIR

これに関する最悪の部分は、予約語 "string"の乱用における典型的なあいまいさであり、これにより、 "example" .c_str()が問題を解決すると誤って信じることになります。

0
Jerry Miller

その価値は、この単純なラッパークラスがC++文字列をchar *に変換するのに役立つことです。

class StringWrapper {
    std::vector<char> vec;
public:
    StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
    }

    char *getChars() {
        return &vec[0];
    }
};
0
bremen_matt

私も同じ問題を抱えていました。そして、私がやったのは、char *の代わりにconst char *を追加するだけです。そして問題は解決しました。他の人が上記で言及したように、それは互換性のあるエラーです。 Cは文字列をchar配列として扱い、C++はそれらをconst char配列として扱います。

0
dilantha111