Code Fix

中級

error: invalid operands to binary ==(構造体同士の==比較)

構造体同士を==で比較しようとしたときに出るエラーです。Cの==は組み込み型専用で、構造体には定義されていません。

エラーメッセージの読み方

main.c:8:11: error: invalid operands to binary == (have 'struct Point' and 'struct Point')
main.c
ファイル名
8
行番号
11
列番号 — この位置でgccが構文解析に失敗しました
invalid operands to binary == (have 'struct Point' and 'struct Point')
内容 — 期待していたもの、または受け付けられなかったもの

このエラーが出る典型パターン

パターン1

 1  #include <stdio.h>
 2  
 3  struct Point { int x, y; };
 4  
 5  int main(void) {
 6      struct Point a = {1, 2};
 7      struct Point b = {1, 2};
 8      if (a == b                        ) {
                           ^
 9          printf("same\n");
10      }
11      return 0;
12  }
main.c:8:11: error: invalid operands to binary == (have 'struct Point' and 'struct Point')

Cの==は組み込み型専用です。構造体を比較するには、メンバを1つずつ==で比較する必要があります。

直し方: a == b を a.x == b.x && a.y == b.y にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  #include <stdio.h>
 2  
 3  struct Color { int r, g, b; };
 4  
 5  int main(void) {
 6      struct Color c1 = {255, 0, 0};
 7      struct Color c2 = {255, 0, 0};
 8      if (c1 == c2                                    ) {
                                  ^
 9          printf("same color\n");
10      }
11      return 0;
12  }
main.c:8:12: error: invalid operands to binary == (have 'struct Color' and 'struct Color')

メンバが3つに増えても事情は同じです。構造体全体の比較演算子はCには存在しません。

直し方: c1 == c2 を c1.r == c2.r && c1.g == c2.g && c1.b == c2.b にします。

この問題を解いてみる →

パターン3

 1  #include <stdio.h>
 2  
 3  struct Pair { int a, b; };
 4  
 5  int main(void) {
 6      struct Pair p1 = {3, 4};
 7      struct Pair p2 = {3, 5};
 8      if (p1 == p2                    ) {
                          ^
 9          printf("equal\n");
10      } else {
11          printf("different\n");
12      }
13      return 0;
14  }
main.c:8:12: error: invalid operands to binary == (have 'struct Pair' and 'struct Pair')

コンパイラは構造体のメンバ構成を知っていても、==による自動比較は生成しません。必ず自分で書く必要があります。

直し方: p1 == p2 を p1.a == p2.a && p1.b == p2.b にします。

この問題を解いてみる →

パターン4

 1  #include <stdio.h>
 2  
 3  struct Size { int w, h; };
 4  
 5  int main(void) {
 6      struct Size s1 = {5, 10};
 7      struct Size s2 = {5, 10};
 8      if (s1 == s2                         ) {
                            ^
 9          printf("same\n");
10      }
11      return 0;
12  }
main.c:8:12: error: invalid operands to binary == (have 'struct Size' and 'struct Size')

サイズを表す構造体でも、==による比較はコンパイルエラーになります。メンバを1つずつ比較します。

直し方: s1 == s2 を s1.w == s2.w && s1.h == s2.h にします。

この問題を解いてみる →

パターン5

 1  #include <stdio.h>
 2  
 3  struct Time { int h, m; };
 4  
 5  int main(void) {
 6      struct Time t1 = {9, 30};
 7      struct Time t2 = {9, 45};
 8      if (t1 == t2                    ) {
                          ^
 9          printf("same\n");
10      } else {
11          printf("diff\n");
12      }
13      return 0;
14  }
main.c:8:12: error: invalid operands to binary == (have 'struct Time' and 'struct Time')

時刻を表す構造体でも同じです。==での丸ごと比較はできず、必ずメンバごとに書きます。

直し方: t1 == t2 を t1.h == t2.h && t1.m == t2.m にします。

この問題を解いてみる →

よくある誤解

構造体もひとつの値のように見えるため==で比較できそうに感じますが、Cはこの比較を自動生成しません。すべてのメンバを1つずつ==で比較する専用の関数を自分で書く必要があります。

実務での勘所

constとして比較を自分で書く以外に、memcmp(&a, &b, sizeof(a))で丸ごとバイト比較する裏技を思いつくかもしれませんが、これは安全ではありません。構造体にはアライメント(メモリ配置の都合)のため、メンバとメンバの間に「パディング」と呼ばれる未使用の隙間が入ることがあり、この隙間の中身は不定です。値としては等しい2つの構造体でも、パディング部分のゴミの値が違っていればmemcmpは「違う」と判定してしまいます。安全に比較するには、メンバを1つずつ明示的に比較する関数を書く必要があります。

演習をはじめる

関連するエラー

他の言語ではどうなるか

広告
広告スロット(未設定)