2017-07-10 12 views
1

私はこのようなstrcpyをしようとしていた。明確化()*編曲

int main() 
    { 
    char *c="hello"; 
    const char *d="mello"; 
    strcpy(c,d); 
    cout<<c<<endl; 
    return 0; 
    } 

これは警告を与え、コードを実行するとセグメンテーションフォールトを生成コンパイル。

警告がある:

警告:「のchar *」に定数文字列から非推奨の変換[-Wwrite-ストリング]
CHAR * C = "こんにちは";

strcpyの宣言は次のとおりです。char * strcpy (char * destination, const char * source);

  1. だから私は(警告に関する)間違っていますか? IMO const charcharを関数の宣言と同じものを使用しています。

  2. c*またはd*は、それがセグメンテーションフォールトをスローしているため、 に、"hello""mello"を保持するためのメモリを割り当てませんか? c*のような変数の初期化/定義はどのように機能しますか?

+5

'char * c =" hello ";'はもはやC++では合法ではありません。 – drescherjm

+1

私はあなたの問題解決を理解していません。警告は 'char * c =" hello ";'を指していますが、あなたは 'strcpy'を正しく呼び出していると主張しています。コンパイラはその部分についても不平を言っていません。 – Rakete1111

+1

*** c *のような変数の初期化/定義はどうしますか?***多くのコンパイラは、文字列リテラルをメモリの変更不可能な領域(OSやhwで保護されています)に配置します。 – drescherjm

答えて

2

コンパイラの警告(およびエラー)は、常に特定のコード行(およびその行の一部)も参照します。問題がどこにあるかに細心の注意を払うことは良い考えです。あなたのケースでは

は、警告がでない程度strcpy、が、約cを初期化を呼び出します。 char *の変更可能なポインタchar"hello"、読み取り専用文字列リテラルを指すポインタを作成しています。これはコンパイラが警告するものです。

これはC++で可能でしたが、(文字列リテラルは不変なので)指定されたメモリを実際に変更してはいけないという警告がありました。 C++ 11以降、文字列リテラルをchar *に変換することは、明示的に禁止されており、警告の代わりにエラーが生成されます。

segfaultの理由は明らかです:strcpyコールで読み取り専用メモリを上書きしようとしています。

正しい解決策は、宛先文字列を格納するために書き込み可能メモリを使用することです。これは、(単に他のローカル変数など)は通常、書き込み可能な新しいchar配列を作成し、かつ効果的に文字列リテラル(その写しの内容で配列を初期化

char c[] = "hello"; 

:このようにあなたはそれを行うことができます)。

もちろん、これはC++なのでchar*strcpy、および他のC-ismsをまったく気にせずに、文字列を格納するにはstd::stringを使用する必要があります。

3

両方の変数が定数リテラルテキストを指しています。

定数リテラルテキストの変更は未定義の動作です。配列へ

置き、テキストをあなたはそれを変更したい場合:

char e[] = "fred"; 
e[0] = 'd'; 
1

あなたがしようとしているコードはTurboCためです++に思えます。コメントにdrescherjmが指摘しているように、char *c="hello";はもはやC++では合法ではありません。

あなたのコードをTurbo C++で試してみると、期待通りに動作しますが、これは現代のC++と同じではありません。

ここで私は間違っています(警告に関する)? IMO関数の宣言と同じconst charとcharを使用しました。

警告は上記の理由によるものですが、警告はstrcpyを使用していないため、宣言にあります。

c *またはd *は、 "hello"と "mello"を保持するメモリを割り当てていないため、セグメント違反が発生していますか? c *のような変数の初期化/定義はどのように機能しますか?

まあ、単にメモリ内のランダムな場所にして文字列を入れて、それをC/Dポインタのポイントを聞かせコンパイラ。ポインターを偶然何か他のものに向けると、データを失う危険があります。