私はクラスを持っています private char str[256];
そしてそれのために私は明示的なコンストラクタを持っています:
explicit myClass(const char *func)
{
strcpy(str,func);
}
私はそれを次のように呼びます:
myClass obj("example");
これをコンパイルすると、次の警告が表示されます。
文字列定数から 'char *'への非推奨の変換
なぜこうなった?
私はクラスを持っています private char str[256];
そしてそれのために私は明示的なコンストラクタを持っています:
explicit myClass(const char *func)
{
strcpy(str,func);
}
私はそれを次のように呼びます:
myClass obj("example");
これをコンパイルすると、次の警告が表示されます。
文字列定数から 'char *'への非推奨の変換
なぜこうなった?
回答:
これは、次のような状況が発生したときに表示されるエラーメッセージです。
char* pointer_to_nonconst = "string literal";
どうして?まあ、CとC ++は文字列リテラルの型が異なります。Cではタイプはcharの配列で、C ++では定数のchar配列です。いずれの場合も、文字列リテラルの文字を変更することは許可されていないため、C ++のconstは実際には制限ではなく、タイプセーフなものです。安全上の理由から、明示的なキャストなしでは、通常、からconst char*
への変換char*
はできません。ただし、Cとの下位互換性のために、C ++言語では引き続き文字列リテラルをaに割り当てることchar*
ができ、この変換が廃止されることについて警告が表示されます。
したがって、どこかconst
でconstの正確さのためにプログラムで1つ以上のが欠落しています。しかし、あなたが私たちに示したコードは、この種の廃止された変換を行わないので問題ではありません。警告は他の場所から来たに違いありません。
const
は、MyClass
コンストラクターからを削除します。次に、const
バックを追加して修正できます。
警告:
文字列定数から 'char *'への非推奨の変換
あなたがどこか(あなたが投稿したコードではない)で何かをしているので、与えられます:
void foo(char* str);
foo("hello");
問題は、文字列リテラル(型付きconst char[]
)をに変換しようとしていることですchar*
。
配列はポインターに合わせて減衰するので、a const char[]
をtoに変換できconst char*
ますが、実行しているのは、ミュータブルを定数にすることです。
この変換はおそらくC互換性のために許可されており、言及された警告を与えるだけです。
同様に答えていません。2 by fnieto-フェルナンドニエトは、この警告が表示されるのは、コード内のどこか(投稿したコードではない)で発生したためです。
void foo(char* str);
foo("hello");
ただし、コードを警告なしで保持したい場合は、コードをそれぞれ変更します。
void foo(char* str);
foo((char *)"hello");
つまり、string
定数をにキャストするだけ(char *)
です。
void foo(char* str)
はありますか?パラメータが非定数として書かれているとしても、私たちはとにかくモディファイできないと思いstr
ましfoo
た。
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");
配列は既に定数ポインターであるため、ポインターの代わりに配列を使用することもできます。
strdup
ます。コードとは異なり、NUL文字を終了するためのスペースを割り当て、割り当てを超過しません。
実際、文字列定数リテラルはconst char *でもchar *ではなく、char []です。かなり奇妙ですが、C ++仕様で記述されています。変更すると、コンパイラがコードセグメントに格納する可能性があるため、動作は未定義になります。
この問題は、コードの最初のどこかにこのマクロを追加することで解決します。または、それをに追加してください<iostream>
。
#define C_TEXT( text ) ((char*)std::string( text ).c_str())
C_TEXT
関数呼び出し(foo(C_TEXT("foo"));
)には問題ありませんが、値が変数のように格納されている場合、未定義の動作を要求していますchar *x = C_TEXT("foo");
- x
(割り当て以外の)の使用は、それが指しているメモリが解放されているため、未定義の動作です。
この問題の理由(char* str = "some string"
他の人が説明している問題よりも検出が難しい)は、を使用している場合ですconstexpr
。
constexpr char* str = "some string";
以前のようにと同様に動作しconst char* str
、警告も発生char*
しないようですが、代わりにとして動作しchar* const str
ます。
定数ポインタ、および定数へのポインタ。差const char* str
とは、char* const str
次のように説明することができます。
const char* str
:strをconst charへのポインターとして宣言します。これは、このポインターが指すデータが定数であることを意味します。ポインターは変更できますが、データを変更しようとすると、コンパイルエラーがスローされます。
str++ ;
:有効。ポインターを変更しており、ポイントされているデータは変更していません。*str = 'a';
:無効です。ポイントされているデータを変更しようとしています。char* const str
:strをcharへのconstポインターとして宣言します。つまり、ポイントは現在一定ですが、ポイントされるデータも一定ではありません。ポインターは変更できませんが、ポインターを使用してデータを変更できます。
str++ ;
:無効です。定数であるポインター変数を変更しようとしています。*str = 'a';
:有効。ポイントされているデータを変更しようとしています。私たちの場合、これはコンパイルエラーを引き起こしませんが、文字列がコンパイルされたバイナリの読み取り専用セクションに入る可能性が高いため、ランタイムエラーを引き起こします。このステートメントは、メモリを動的に割り当てた場合に意味があります。char* const str = new char[5];
。const char* const str
:strをconst charへのconstポインターとして宣言します。この場合、ポインターもポイントされているデータも変更できません。
str++ ;
:無効です。定数であるポインター変数を変更しようとしています。*str = 'a';
:無効です。このポインターが指すデータを変更しようとしていますが、これも定数です。私の場合の問題は、視覚的には前者に近いように見えるため、constexpr char* str
としてconst char* str
ではなくとして動作することを期待していたということでしたchar* const str
。
また、生成される警告はとconstexpr char* str = "some string"
は少し異なりchar* str = "some string"
ます。
constexpr char* str = "some string"
:ISO C++11 does not allow conversion from string literal to 'char *const'
char* str = "some string"
:ISO C++11 does not allow conversion from string literal to 'char *'
。Cの意味不明な↔英語コンバーターを使用して、C
宣言を簡単に理解できる英語のステートメントに、またはその逆に変換できます。これはC
唯一のツールであるため、に限定されているもの(constexprなど)をサポートしませんC++
。
その価値については、この単純なラッパークラスがC ++文字列の変換に役立つことがわかりましたchar *
。
class StringWrapper {
std::vector<char> vec;
public:
StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
}
char *getChars() {
return &vec[0];
}
};
以下は解決策を示しています。文字列をcharの定数配列への変数ポインタに割り当てます(文字列はcharの定数配列への定数ポインタ-長さ情報):
#include <iostream>
void Swap(const char * & left, const char * & right) {
const char *const temp = left;
left = right;
right = temp;
}
int main() {
const char * x = "Hello"; // These works because you are making a variable
const char * y = "World"; // pointer to a constant string
std::cout << "x = " << x << ", y = " << y << '\n';
Swap(x, y);
std::cout << "x = " << x << ", y = " << y << '\n';
}
strncpy(str, func, 255)
代わりに使用する必要がありstrcpy(str, func)
ます。そして、strncpyが追加しないため、文字列の最後に '\ 0'を追加することを忘れないでください。