3

私は問題を抱えています.2つのポインタのアドレスがここで問題になっているのと同じであることがわかりました( 2つのポインタのアドレスは同じです), ブルームーンからも回答がありました. これにより、さらに疑問が生じました。両方のポインターが同じアドレスを持っているため、ポインターの1つの値を変更すると思ったので、他のポインターでも期待値が変更されます(同じアドレスを持っているため)。しかし、それはセグメンテーション違反を引き起こします。以下のコードでそれを示しています。

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

int main()
{
    char * p = "abc";
    char * p1 = "abc";
    printf("%d\n %d\n", (void *)p, (void *)p1);
    printf("%s\n %s\n", p, p1);
    *p = 'b';
    printf("%d\n %d\n", p, p1);
    printf("%s\n %s\n", p, p1);
}
4

4 に答える 4

6

C90、6.1.4

プログラムがいずれかの形式の文字列リテラルを変更しようとした場合、動作は未定義です。

あなたの場合、この未定義の動作はあなたに有利であるため、Seg fault.Other を使用してこの印刷ポインターを使用することはお勧めでき%dません。使用する必要があります%p

ブルームーンのあなたの与えられたリンク回答から今

p同じアドレスを指している場合と指していない場合があるため、常にandを 2 つの異なるポインターとして扱う必要がp1あります (内容が同じであっても)。コンパイラの最適化に頼るべきではありません。

于 2013-09-30T09:36:49.490 に答える
3

コード

char * p = "abc";

文字列リテラルを読み取り専用メモリに配置できるため、技術的には変更しないでください。これにより、セグフォルトが発生する可能性があります。これが、2 つのポインターが同じである可能性がある理由でもあります...コンパイラーは、両方が同じ文字列リテラルを使用していることを認識するのに十分賢いため、リテラルの 1 つのインスタンスのみを格納します。

として宣言した場合

char p[] = "abc"

次に、これにより、スタック上に 4 文字 (3 および 1 つの null ターミネータ) の読み取り/書き込み可能な配列が作成され、それを変更することができますが、...

char p[] = "abc";
char p1[] = "abc";

どちらもスタック上の個別のストレージで作成されていることがわかりp1 != pます(グローバルではないと想定しています)

また、printfポインター値を出力するために使用する場合は、使用する方が良いと思います%p

于 2013-09-30T09:38:45.967 に答える
3
char * p = "abc";
*p = 'b';

読み取り専用メモリを変更しようとしているため、未定義の動作が発生します。この定数文字列リテラルが存在するメモリを変更することはできません。

代わりに、このリテラルを使用して配列を初期化します。

char myStr[] = "abc";
char *p = &myStr[0];
char *p2 = &myStr[0];  // <-- p and p2 point to the same address now
*p = 'b';
printf("%s\n", p2);    // <-- prints bbc
于 2013-09-30T09:36:01.680 に答える
2

文字列リテラルは読み取り専用メモリ セグメントに格納されるため、それを変更しようとするとセグメンテーション エラーが発生します。これは、文字列リテラル データが多くのポインターによって参照される可能性があり、それを変更すると他の定数文字列が変更されるためです。

于 2013-09-30T09:35:44.920 に答える