1

私が疑問に思っているのは、文字列を char* に変換すると、新しい char* が元のリテラル文字列と等しくないように見える理由です。

私が持っている場合:

//raw versions of the string:
string s = "fun";
char* c = "fun";

char* s_convert = strdup(s.c_str()); //converting the string to char*

printf("(string) == 'fun' -> %d\n", (s == "fun"));
printf("(char*) == 'fun' -> %d\n", (c == "fun"));
printf("(char* convert) == 'fun' -> %d\n", (s_convert == "fun"));

printf("(string) == (char*) -> %d\n", (s == c)); //does new char* equal original string

生成:

(string) == 'fun' -> 1 //true
(char*) == 'fun' -> 1  //true
(char* convert) == 'fun' -> 0 //false
(string) == (char* convert) -> 1 //true

したがって、変換された char* は元の文字列と同じままです。しかし、何らかの理由char* s_convertで、元のリテラル文字列と等しくありませんが、元の文字列はstring sそうです。

なぜこれが起こるのですか?そして、これを引き起こさない文字列を char* に変換できるより良い方法はありますか?

4

6 に答える 6

5

ポインターの場合、==ポインター値を比較します。ポインターが C スタイルの文字列 (単一の文字や終端されていない配列ではなく) を指していることを知る方法がなく、それが指すものを調べません。関数の目的は文字列の新しいコピーにメモリを割り当てることであるため、によって返されるポインタはstrdup文字列リテラルのアドレスにはなりません。

なんらかの理由で本当に C スタイルの文字列をいじる必要がある場合は、strcmp. しかし、C++ 文字列ははるかに便利です。よほどの理由がない限り使用してください。

于 2014-10-30T15:48:06.300 に答える
2

1 つずつ比較してみましょう。

printf("(string) == 'fun' -> %d\n", (s == "fun"));

std::string変数を文字列リテラルと比較します。期待どおりに動作します (つまりs、文字列 "fun" が含まれているstd::stringかどうかを実際にチェックします) operator==

printf("(char*) == 'fun' -> %d\n", (c == "fun"));

cに格納されているアドレスを文字列リテラル "fun" のアドレスと比較します。結果は true または false になります。あなたの場合、コンパイラがコードを最適化したため、それは本当です。「fun」を複数回使用し、文字列リテラルをメモリに1回だけ格納するため、アドレスは常に同じになります。たとえば、c別の翻訳単位でリテラル "fun" が割り当てられていた場合、結果は false になります。

printf("(char* convert) == 'fun' -> %d\n", (s_convert == "fun"));

s_convertに格納されているアドレスを文字列リテラル "fun" のアドレスと比較します。前述のように、文字列リテラル "fun" には、コンパイラによって選択された特定のアドレスがあります。std::string明示的にコピーされた文字列と等しいとは比較されません (変数からのものであることは関係ありません)。はstrdup新しく割り当てられたメモリを作成するため、アドレスは以前にメモリに存在したものと比較されません。

printf("(string) == (char*) -> %d\n", (s == c)); //does new char* equal original string

std::stringここでも、を C スタイルの文字列と比較します。これは実際に文字列を比較し、オーバーロードされたof のおかげsで、アドレスに格納されている null で終わる文字列が含まれているかどうかをチェックするため、結果は true です。coperator==std::string

std::string要約すると、観察される効果は、と null で終わる C スタイルの文字列との間の変換とはまったく関係がないか、ほとんど関係がありません。比較すると思うものを比較しないだけです。strcmpnull で終わる「生の」文字列を比較する場合、または何か他のものと==比較する場合に使用すると、期待する結果に賭けることができます。std::string

于 2014-10-30T15:57:03.113 に答える
1

strdup は文字列をコピーし、メモリに割り当てられた新しい文字列へのポインターを返します。このポインターは元の文字列とは異なるアドレスを持っているため、strcmp() を使用して 2 つを比較できますが、これらの文字列が存在するメモリ位置が異なるため、ポインターの比較は失敗します。

于 2014-10-30T15:46:09.343 に答える
1

strcmpを比較するために常に使用しchar *ます。

于 2014-10-30T15:45:36.307 に答える
0

使用する必要があります

0 == strcmp( c, "fun" );

それ以外の

c == "fun";
于 2014-10-30T15:51:01.670 に答える
0

ポインターで等値演算子を使用すると、オーバーロードがない限り、ポインターが比較されます。そのため、ポインターとポインターを文字列リテラルとs_convert == "fun"比較します。 s_convert"fun"

それが機能する理由c == "fun"は、cすでにその文字列リテラルを指しているためです。

于 2014-10-30T15:48:23.130 に答える