Cでの文字配列と==演算子の比較
-
05-07-2019 - |
質問
" strings"を比較する正しい方法を知っています。 Cの場合は strcmp
を使用しますが、いくつかの文字配列を ==
演算子と比較してみたところ、奇妙な結果が得られました。
次のコードを見てください:
int main()
{
char *s1 = "Andreas";
char *s2 = "Andreas";
char s3[] = "Andreas";
char s4[] = "Andreas";
char *s5 = "Hello";
printf("%d\n", s1 == s2); //1
printf("%d\n", s3 == s4); //0
printf("%d\n", s1 == s5); //0
}
最初の printf
は、 1
を正しく印刷し、それらが等しくないことを通知します。しかし、文字配列を比較すると、 ==
が 0
を返している理由を誰かに説明できますか?
最初の printf
が 1
(つまり、等しい)を返し、文字配列が 0
?
解決
==はメモリアドレスを比較しています。
コンパイラーは、スペースを節約するために、s1とs2が同じ静的データを指すようにしている可能性があります。
ie。 「アンドレアス」コードの最初の2行は実行可能データに保存されます。 C標準では、これらの文字列は定数であるため、2つのポインターを同じストレージを指すように最適化しています。
char []行は、データを変数にコピーすることで変数を作成するため、実行中にスタックの異なるアドレスに保存されます。
他のヒント
ええと... ==
が1を出力する場合、それは が等しいことを意味します。文字列の相対的な順序を返すstrcmpとは異なります。
文字列ではなくアドレスを比較しています。最初の2つは定数であり、一度だけ作成されます。
int main()
{
char *s1 = "Andreas";
char *s2 = "Andreas";
char s3[] = "Andreas";
char s4[] = "Andreas";
char *s5 = "Hello";
printf("%d\n", s1 == s2); //1
printf("%p == %p\n", s1, s2);
printf("%d\n", s3 == s4); //0
printf("%p != %p\n", s3, s4);
printf("%d\n", s1 == s5); //0
printf("%p != %p\n", s1, s5);
}
コンピューターに出力しますが、アイデアは得られます:
1
0x1fd8 == 0x1fd8
0
0xbffff8fc != 0xbffff8f4
0
0x1fd8 != 0x1fe0
Wait a sec ... 1は真を意味し、0は偽を意味します。だからあなたの説明は部分的に逆です。最初の2つの文字列が等しいように見える理由については、コンパイラは定数文字列(s1 / 2)を一度だけ作成しました。
s1 == s2
は" (char *)==(char *)
"を意味します。または、アドレスが同じであること。
s3 == s4
でも同じです。それは" 配列がポインターになります"職場で。
そして、比較結果の意味が間違っています:
0 == 0; /* true; 1 */
42 == 0; /* false; 0 */
"foo" == "bar"; /* false (the addresses are different); 0 */
s1からs5までのすべての値は char そのものではなく、 char へのポインタです。したがって、比較しているのは、文字列自体ではなく、各文字列のメモリアドレスです。
このようにアドレスを表示すると、比較演算子が実際に何に取り組んでいるかを見ることができます:
#include <stdio.h>
int main() {
char *s1 = "Andreas";
char *s2 = "Andreas";
char s3[] = "Andreas";
char s4[] = "Andreas";
char *s5 = "Hello";
printf("%p\n", s1); // 0x80484d0
printf("%p\n", s2); // 0x80484d0
printf("%p\n", s3); // 0xbfef9280
printf("%p\n", s4); // 0xbfef9278
printf("%p\n", s5); // 0x80484d8
}
文字列がメモリ内で正確に割り当てられる場所は、実装固有です。この場合、s1とs2は同じ静的メモリブロックを指していますが、その動作が移植可能であるとは思わないでしょう。
文字列を比較することはできませんが、ポインターを比較することはできます。