web-dev-qa-db-ja.com

関数パラメーターの文字列

int main()
{
        char *x = "HelloWorld";
        char y[] = "HelloWorld";

        x[0] = 'Z';
        //y[0] = 'M';

        return 0;
}

上記のプログラムでは、HelloWorldは読み取り専用セクション(つまり、文字列テーブル)にあります。 xはその読み取り専用セクションを指しているため、その値を変更しようとしても未定義の動作になります。

ただし、yはスタックに割り当てられ、HelloWorldはそのメモリにコピーされます。そのため、yの変更は正常に機能します。 文字列リテラル:ポインタと文字配列

これが私の質問です:

次のプログラムでは、両方のchar *arrおよびchar arr[]は、コンテンツが変更された場合にセグメンテーション違反を引き起こします。

void function(char arr[])
//void function(char *arr)
{
   arr[0] = 'X';
}        
int main()
{
   function("MyString");    
   return 0;
}
  1. 関数パラメーターのコンテキストでどのように違いますか?
  2. 関数パラメーターにメモリは割り当てられませんか?

あなたの知識を共有してください。

11
Jeyaram

関数パラメーターリスト内では、char arr[]char *arrと完全に同等であるため、定義のペアと宣言のペアは同等です。

void function(char arr[]) { ... }
void function(char *arr)  { ... }

void function(char arr[]);
void function(char *arr);

問題は呼び出しコンテキストです。関数に文字列リテラルを提供しました。文字列リテラルは変更できません。関数が、与えられた文字列リテラルを変更しようとしました。プログラムが未定義の動作を呼び出し、クラッシュしました。すべて完全にコーシャ。

文字列リテラルをstatic const char literal[] = "string literal";であるかのように扱い、変更を試みないでください。

22
function("MyString");

と類似しています

char *s = "MyString";
function(s);

"MyString"はどちらの場合も文字列リテラルであり、どちらの場合も文字列は変更できません。

function("MyString");

文字列リテラルのアドレスをfunctionに引数として渡します。

6
ouah

char * arr;上記のステートメントは、arrが文字ポインターであり、1文字または文字列を指すことができることを意味します

&char arr [];上記のステートメントは、arrは文字列であり、できるだけ多くの文字または1文字を格納できるが、常に '\ 0'文字でカウントされるため、文字列になることを意味します(たとえば、char arr [] = "a"はchar arr [] = {'a'、 '\ 0'})

ただし、呼び出された関数のパラメーターとして使用する場合、渡される文字列は形式引数に文字ごとに格納され、違いはありません。

1
Nitin Singh