web-dev-qa-db-ja.com

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

可能性のある複製:
C++は文字列定数から 'char *'への非推奨の変換

文字列をchar *経由で関数に渡したい。

 char *Type = new char[10];
 Type = "Access";  // ERROR

しかし、私はこのエラーを受け取ります:

 error: deprecated conversion from string constant to 'char*'

どうすれば修正できますか?

26
mahmood

タイプを本当に変更したい場合:

char *Type = new char[10];
strcpy( Type, "Access" );

アクセスを変更したくない場合:

const char *Type = "Access";

ただし、CおよびC++のchar配列には多くの問題があることに注意してください。たとえば、newの呼び出しが成功したかどうか、または例外をスローするかどうかは本当にわかりません。また、strcpy()は10文字の制限を超える可能性があります。

したがって、後でタイプを変更する場合は、検討することができます。

std::string Type = "Access";

そして、それを変更したくない場合:

const std::string Type = "Access";

... std::stringを使用する利点は、これらすべての問題に対処できることです。

38
Baltasarq

ここでいくつかのことが行われています。

char *Type = new char[10];

これにより、Typeという名前のchar*ポインターが作成され、新しく割り当てられた10要素配列の最初の要素を指すように初期化されます。

Type = "Access";  // ERROR

この割り当ては、あなたが思っていることをしません。 6文字の文字列"Access"(終端の'\0'を含む7文字)を作成した配列にコピーしません。代わりに、その配列の最初の要素にpointerをポインターTypeに割り当てます。それには2つの問題があります。

最初に、Typeの以前の値を上書きします。今割り当てた10文字の配列には、それを指すものは何もありません。アクセスできなくなったり、割り当てを解除することさえできなくなります。これはメモリリークです。

これはコンパイラが不満を言っていることではありません。

次に、文字列リテラルは静的に割り当てられたconst配列を作成します(「静的に割り当てられた」とは、プログラムの実行全体に存在することを意味します)。 Typeは、const修飾子で宣言されていません。コンパイラがTypeを文字列"Access"にポイントすることを許可した場合、そのポインターを使用して(変更を試みて)変更できます。

Type = "Access";
Type[0] = 'a'; // try to change the string to "access"

constの目的は、読み取り専用のものを変更したり、変更しようとしたりすることを防ぐことです。そのため、constポインターオブジェクトに非constポインター値を割り当てることはできません。

C++でプログラミングしているので、おそらくstd::stringを使用する方が良いでしょう。

12
Keith Thompson

文字列をchar *経由で関数に渡したい。

以下は、char *を介して文字列を関数に渡す方法です(関数シグネチャの必須のconstキーワードに注意してください)。

#include <iostream>
void f(const char* p) {
  std::cout << p << "\n";
}

int main() {
  f("Access");
}

しかし、既存の関数を呼び出していて、その署名を変更できない場合はどうでしょうか?

関数が引数ポインターを介して書き込みを行わないという外部保証がある場合、

#include <iostream>
void f(char* p) {
  std::cout << p << "\n";
}

int main() {
  f(const_cast<char*>("Access"));
}

一方、関数が文字列に書き込む場合、文字列にスペースを割り当てる必要があります。

#include <iostream>
void f(char* p) {
  *++p;
  std::cout << p << "\n";
}

int main() {
  // Allocate read-write space on the heap
  char *p = new char[strlen("Access"+1)];
  // Copy string to allocated space
  strcpy(p, "Access");
  f(p);
  delete p;
}

または、

#include <iostream>
void f(char* p) {
  *++p;
  std::cout << p << "\n";
}

int main() {
  // Allocate read-write space on the stack
  char arr[] = "Access";
  f(arr);
}

しかし、これまでの最善の方法は、ポインタのミスヘガ全体を回避することです。

#include <iostream>
void f(const std::string& p) {
  std::cout << p << "\n";
}

int main() {
  f("Access");
}
5
Robᵩ

ここには、コーディングの問題ではなく、基本的な操作の問題があります。

Cのchar配列の内容を変更する場合、-代入演算子を使用しないでください。代わりに、基になるポインターの値が変更されます。うん.

代わりに、C文字列ライブラリルーチンを使用することになっています。たとえば、strcpy (Type, "Access");は、文字列リテラル "Access"を文字配列にコピーし、最後に重要なヌル文字を付けます。

(タグが示すように)C++を使用している場合は、おそらくstd::string charの配列の代わりに。割り当ては、期待どおりに機能します。

0
T.E.D.