9

文字列を逆にしようとしています。

これは私が試したコードです:

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

int main(){
    char *c="I am a good boy";
    printf("\n The input string is : %s\n",c);
    printf("\n The length of the string is : %d\n",strlen(c));
    int i,j;
    char temp;
    int len=strlen(c);
    for(i=0,j=len-1;i<=j;i++,j--)
    {
            temp=c[i];
            c[i]=c[j];
            c[j]=temp;
    //printf("%c\t%c\n",*(c+i),*(c+(len-i-1)));
    }
    printf("\n reversed string is : %s\n\n",c);
}

コードは を出力しBus error : 10ます。

しかし、同じコードを次のように書き直すと:

int main(void)
{
    char *str;
    str="I am a good boy";
    int i,j;
    char temp;
    int len=strlen(str);
    char *ptr=NULL;
    ptr=malloc(sizeof(char)*(len));
    ptr=strcpy(ptr,str);
    for (i=0, j=len-1; i<=j; i++, j--)
    {
        temp=ptr[i];
        ptr[i]=ptr[j];
        ptr[j]=temp;
    }
    printf("The reverse of the string is : %s\n",ptr);
}

それは完全にうまく機能します。

最初のコードがバス エラーまたはセグメンテーション エラーをスローするのはなぜですか?

4

5 に答える 5

16

バス エラーが発生するのは、多くの (最新のほとんどまたはすべてではないにしても) C コンパイラでは、文字列リテラルが読み取り専用メモリに割り当てられるためです。

文字列をその場で逆にしています。最初のコード スニペットでは、文字列リテラルに書き込もうとしています。良い考えではありません。

2 番目のケースでは、文字列を malloc してヒープに置きました。その文字列を逆にしても安全です。

補遺

segfaults とバス エラーについて尋ねたコメント投稿者にとって、それは素晴らしい質問です。私は両方を見てきました。Mac でのバス エラーは次のとおりです。

$ cat bus.c 
char* s = "abc"; int main() {s[0]='d'; return 0;}

$ gcc --version bus.c && ./a.out
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5659)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Bus error

他のオペレーティング システム/コンパイラでは、実際に segfault が発生する可能性があります。

于 2011-09-18T01:05:54.170 に答える
6

ヒープにコピーすることも 1 つのオプションです。ただし、ローカル (スタック) 配列を割り当てたいだけの場合は、次のようにすることができます。

char str[] = "I am a good boy";

次に、定数文字列がスタックにコピーされます。

于 2011-09-18T01:15:51.173 に答える
1

の形式で指定された文字配列"I am a good boy"は、通常、定数です。変更することはできません。それが、最初の亜種がクラッシュする理由です。2 つ目は、データのコピーを作成してから変更するため、そうではありません。

于 2011-09-18T01:07:33.893 に答える
0

char * str="私はいい子です"; リテラルとして扱われ、それを変更しようとすると、バスエラーが発生します。これは、const char * str = "I am a good boy"と同等です。つまり、定数文字列へのポインタであり、定数文字列を変更しようとすることは許可されていません。

編集:malloc()を実行し、元の文字列のコピーで遊んでいる瞬間、ptrは'const char *'タイプではなく、'char * ptr'であり、文句を言いません。

于 2011-09-18T15:16:45.330 に答える
0

c++ (g++) でコンパイルすると、このエラーを防ぐように設計された非 const char* に文字列リテラルを代入することの非推奨が示されます。

ed@bad-horse:~/udlit_debug$ g++ ../buserr.cpp 
../buserr.cpp: In function ‘int main()’:
../buserr.cpp:5:13: warning: deprecated conversion from string constant to ‘char*’
../buserr.cpp:7:61: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘size_t’

関連する警告は 5 行目にあります。

示されているように宣言を const char * に変更すると、リテラル文字列への割り当てが防止されます。

これは、警告を無視してはならない理由についての教訓でもあります。

于 2011-09-24T02:37:35.070 に答える