3

ここでの私の最初の質問。2D配列の代わりにポインターの配列を使用しています。ここで、要素を表示するために*(arr [i] + j)を使用できます。ここで、arrは配列iは行を示し、jは列を示します。ただし、同じ表記を使用して任意の要素に値を割り当てようとすると、コードが機能しなくなります。コンパイルエラーは発生しませんが、実行すると動作を停止します。誰か助けてもらえますか?

これが私のコードです

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    int i,j,k;
    char temp2, temp, *arr[] = {
        "Brinda Roy", 
        "Rakesh Bai", 
        "Neha Saxen", 
        "Ankit Jain"};

    printf("%c",*(arr[3]+8));

    for(i=0;i<4;i++){
        for(j=0, k=9; j<=4, k>=5; j++, k--){
            temp =*(arr[i]+j);
            *(arr[i]+j)=*(arr[i]+k);
            *(arr[i]+k)=temp;
        }

    }

    printf("\nThe array is ");

    for(i=0; i<4; i++){
        printf("\n%s",arr[i]);
    }

    getch();
    return 0;
}
4

4 に答える 4

5

ランタイム クラッシュは、 で文字列リテラルを変更したことが原因ですarr。文字列リテラル"Brinda Roy""Rakesh Bai""Neha Saxen"およびは、プログラムの読み取り専用セクションに格納される可能性があるため、 として"Ankit Jain"扱う必要があります。const char[]以下のコメントに記載されているように、それらの値を変更しようとすると、未定義の動作が発生します。

これらの読み取り専用文字列を編集したい場合は、それらのコピーを非constバッファに作成する必要があります。


もしあなたがそうするなら:

char *str = "message"

strが指すデータは読み取り専用メモリを指しているため、変更しないでください。


もしあなたがそうするなら:

char str[] = "message"

読み取り専用の文字列リテラルが配列にコピーされているため、が指すデータを変更できます。str"message"str


あなたのコードは、上記の最初のシナリオに当てはまります。

于 2012-06-28T23:14:31.153 に答える
3

C では、このスタイルを使用してソースで定義された文字列を読み取り専用のデータ セクションに格納できます。この出力を確認します。

$ cat storage.c
int main(int argc, char* argv[]) {
    char *arr[] = {"hello", "world"};
    arr[1][1]='a';
    return 0;
}
$ make storage
cc     storage.c   -o storage
$ readelf -p.rodata storage

String dump of section '.rodata':
  [     4]  hello
  [     a]  world

私のコンパイラは、文字列を.rodata読み取り専用データ セクションに配置しました。プログラムで を に更新しようとするとoaプログラムが停止します。

$ ./storage 
Segmentation fault (core dumped)

これは一般に、文字列を次のように定義するすべてのコードに適用されます。

char *foo = "string";

プログラム ソースで変更可能な文字列を作成する場合は、代わりに次のように記述します。

char foo[] = "string";

変更可能な文字列の配列を作成するための構文がどうなるかは完全にはわかりません。少なくとも次の醜いアプローチは機能しますが、もっと良い方法があると確信しています:

char a1[] = "hello";
char a2[] = "world";
char *arr[] = {a1, a2};
于 2012-06-28T23:15:42.227 に答える
2

文字列リテラルを変更しようとしています。これは禁止されています。"abc"これは型システム ( is not )によって強制されていませんがconst char*、文字リテラルを変更すると、"abc"[1]='c'未定義の動作が発生することに注意してください。

データを書き込み可能な場所に移動する必要があります。これを行う最も簡単な方法は、標準ではありませんが、次のstrdup関数を使用することです。

for(i=0; i<4; i++)
  arr[i]=strdup(arr[i]);

これにより、文字列のヒープにメモリが割り当てられ、文字列がコピーされます。関数がない場合は、 、およびstrdupを使用して実装する必要があります。mallocstrlenmemcpy

動的に割り当てられたメモリの場合と同様に、解放する必要があることに注意してください。そうしないと、メモリ リークが発生します。

ところで、二重ポインタ配列と多次元配列の両方にアクセスする通常の方法はarr[i][j].

于 2012-06-28T23:14:31.030 に答える
1

この方法で予約されたメモリを変更することはできません。

{"Brinda Roy", 
 "Rakesh Bai", 
 "Neha Saxen", 
 "Ankit Jain"};

このように char* を定義すると、メモリの読み取りのみになります。

于 2012-06-28T23:17:17.233 に答える