8

MinGWを使用してこのプログラムを実行すると、「=」として出力されます

#include<iostream>

using namespace std;

int main()
{
 char *str1 = "Hello";
 char *str2 = "Hello";

 if(str1==str2)
 cout<<"=";
 else
 cout<<"!=";


 return 0;
}

ただし、論理的には != である必要があります。これらはポインターであり、異なるメモリ位置を指しているからです。このコードを Turbo C++ で実行すると、!= が表示されます。

4

5 に答える 5

14

それらがポインターであるという点で、あなたは正しいです。ただし、それらが異なる場所を指しているかどうかは、実装によって異なります。コンパイラが文字列リテラルを 1 回だけ格納し、そのアドレスがコード内で使用されている場合は常にそのアドレスを使用することは完全に有効です。

于 2012-11-22T15:14:08.390 に答える
10

2 つのポインタが異なるメモリ位置を指しているという保証はありません。おそらく、最適化またはコンパイラが独自のルールを使用しているためです...動作は「実装定義」です。

標準 (C++11 §2.14.5 文字列リテラル) によると:

すべての文字列リテラルが異なる (つまり、重複しないオブジェクトに格納される) かどうかは、実装で定義されます。

于 2012-11-22T15:32:18.680 に答える
4

これは予想される結果です。これは、基になるアセンブリを調べることで確認できます。たとえば、次のようにビルドすると:

g++ -S ptr.c

次に、ファイル出力 (ptr.s) に次の内容が表示されます。

        .file   "ptr.c"
        .def    ___main;        .scl    2;      .type   32;     .endef
        .section .rdata,"dr"
LC0:
        .ascii "Hello\0"               ; Note - "Hello" only appears once in
                                       ; this data section!
LC1:
        .ascii "=\0"
LC2:
        .ascii "!=\0"
        .text
.globl _main
        .def    _main;  .scl    2;      .type   32;     .endef
_main:
        [... some stuff deleted for brevity ...]
LCFI5:
        call    ___main
        movl    $LC0, -12(%ebp)        ; This sets str1
        movl    $LC0, -8(%ebp)         ; This sets str2
        movl    -12(%ebp), %eax

2 つの重要なビットについてコメントしました。'Hello' の出現は、基になるコードの rdata セクションに 1 つだけあり、str1 と str2 が最後に設定されており、両方とも同じラベルを指していることがわかります: LC0. これは、「Hello」が文字列リテラルであり、重要なことに定数であるためです。

他の人が指摘しているように、これは基準の下では完全に合法です。

于 2012-11-22T15:58:41.510 に答える
3

のような文字列リテラルの型は"Hello"const char配列であるため、変更が許可されていないものに 2 つのポインターを向けています。

C++ 標準では、コンパイラは同一の定数値を自由にマージできます (コンパイラはそうする必要がないことに注意してください)。

関連: したがって、宣言は無効であり、次のように変更する必要があります。

const char *str1 = "Hello";
const char *str2 = "Hello";

または必要に応じて

char const *str1 = "Hello";
char const *str2 = "Hello";

右から左に読むとうまく読めます:

str1 is a pointer to const char

.

于 2012-11-22T16:13:07.607 に答える
0

char *str1 = "Hello";-- この行は (多くのコンパイラで) 許可されていますが、実際に行うのは悪い考えです。これは基本的に C との下位互換性のためにのみ許可されており、実際に *str1 に書き込むと未定義の動作になります。これを行うときに警告を表示するコンパイラ設定を見つけることをお勧めします。コンパイラにそのような警告がない場合は、新しいコンパイラを見つけることをお勧めします。

"String literals"C++ 標準は、コンパイラーと実行環境に、どこに保管するかについて途方もない自由度を与えます。"literal"の部分へのポインターを"String literals"のポインター値として文字通り使用でき、"literal"それらを編集しようとしたときにセグメンテーション違反になるメモリにそれらを保存することは予想外ではありません。

char buf1[] = "Hello";とは根本的に異なることを行うことに注意してください。char* str1 = "Hello";実際にbuf1は文字でバッファを初期化し{'H','e','l','l','o','\0'}ます。

于 2012-11-22T15:37:28.780 に答える