web-dev-qa-db-ja.com

等号演算子==を使用して、Cで2つの文字列が等しいかどうかを比較する

_int main (int argc, **argv)
{
       if (argv[1] == "-hello")
            printf("True\n");
       else
            printf("False\n");
}
_
#./myProg -hello 
 False 

どうして? strcmp(argv[1], "-hello") == 0がtrueを返すことに気づきましたが、なぜ等号演算子を使用して2つのC文字列を比較できないのですか?

16
Carlo del Mundo

argv[1](たとえば)は実際には文字列へのポインタです。つまり、ポインタを比較するだけです。

18

Cの文字列を==で比較することはできません。これは、Cコンパイラには文字列リテラル以外の文字列に関する手掛かりがないためです。

コンパイラーは、どちらかの側でchar*との比較を見るので、ポインター比較を行います(ポインターに格納されているアドレスを比較します)。

Cでは、ほとんどのコンテキストで、配列は「最初の要素へのポインタに減衰します」。

したがって、配列"foobar"そして、ほとんどのコンテキストでそれを使用すると、ポインタに減衰します。

if (name == "foobar") /* ... */; /* comparing name with a pointer */

配列の内容somethingを比較したいもの。あなたはそれを手動で行うことができます

if ('p' == *("foobar")) /* ... */; /* false: 'p' != 'f' */
if ('m' == *("foobar"+1)) /* ... */; /* false: 'm' != 'o' */
if ('g' == *("foobar"+2)) /* ... */; /* false: 'g' != 'o' */

または自動的に

if (strcmp(name, "foobar")) /* name is not "foobar" */;
12
pmg

C文字列などは存在しないからです。

Cでは、文字列は通常、charの配列、またはcharへのポインタ(これはほとんど同じです)です。ポインター/配列をconst配列と比較しても、期待される結果は得られません。

更新:「C文字列なし」が意味することは、Cに文字列がないことです。通常「C文字列」と呼ばれるものは、言語に依存しません(「Pascal文字列」と同様)、それは文字列をnullとして表現したものです-文字で終了する線形配列。

7
jv42

Cでは、文字列値(文字列リテラルを含む)はcharの後に0ターミネータが続く配列として表され、_==_演算子を使用して配列の内容を比較することはできません。言語は単に操作を定義しません。

sizeofまたは_&_演算子のオペランドである場合、または宣言内の別の配列を初期化するために使用されている文字列リテラルである場合を除き、 "N-element array of T "のタイプは暗黙的に" pointer to T "に変換(減衰)され、式の値は配列の最初の要素のアドレスになります。

だからあなたが書くとき

_if (argv[1] == "-hello")
_

コンパイラは、式_"-hello"_を「7要素配列のchar」から「pointer to char」に暗黙的に変換し(_argv[1]_はすでにポインタ型です)、式の値は- address文字_'-'_の。つまり、_==_が比較するのは、2つのpointer値です。これらは、(ほとんどの場合)_"-hello"_と_argv[1]_(ほとんどの場合)が占めるため、決して等しくなることはありません。メモリ内のさまざまな領域。

これが、strcmp()などのライブラリ関数を使用して文字列値を比較する必要がある理由です。

5
John Bode

C文字列が存在しないためです。それらは\0で終わる文字配列です。

等価演算子==は、配列の最初の要素へのポインターが同じであることをテストします。それは辞書式に比較しません。

一方、"-hello" == "-hello"mayはゼロ以外の値を返しますが、これは==演算子が辞書編集的に比較することを意味するものではありません。それは他の事実によるものです。

辞書編集で比較したい場合は、いつでもできます

#define STR_EQ(s1,s2)    \
   strcmp(s1,s2) == 0

よく読んでいると思いますが、あなたはc ++としてタグ付けしました。だからあなたは

 std::string arg1 ( argv[1] );

 if (arg1 == "-hello"){
    // yeahh!!!
 }
 else{
    //awwwww
 }
3
Tom

文字列はCのネイティブ型ではありません。この例で比較しているのは2つのポインタです。 1つは最初の引数に対するもので、もう1つは「-hello」の内容を持つ静的文字配列です。

あなたは本当にstrncmpか似たようなものを使いたいのです。

2
kanaka

==を使用しているときは、ポインタを比較しています。つまり、2つのオペランドがメモリ内の同じ文字列を参照している場合、trueを返します。したがって、辞書式に文字列を比較する場合の使用には適していません。

1
waffle paradox

C文字列は文字の配列だからです。配列は単に配列の最初の要素へのポインタであり、==を使用して2つのポインタを比較すると、それらが指す値ではなく、それらが指すメモリアドレスが比較されます。

0
Anthony