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 }
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 }
メンバが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 }
コンパイラは構造体のメンバ構成を知っていても、==による自動比較は生成しません。必ず自分で書く必要があります。
直し方: 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 }
サイズを表す構造体でも、==による比較はコンパイルエラーになります。メンバを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 }
時刻を表す構造体でも同じです。==での丸ごと比較はできず、必ずメンバごとに書きます。
直し方: t1 == t2 を t1.h == t2.h && t1.m == t2.m にします。
よくある誤解
構造体もひとつの値のように見えるため==で比較できそうに感じますが、Cはこの比較を自動生成しません。すべてのメンバを1つずつ==で比較する専用の関数を自分で書く必要があります。
実務での勘所
constとして比較を自分で書く以外に、memcmp(&a, &b, sizeof(a))で丸ごとバイト比較する裏技を思いつくかもしれませんが、これは安全ではありません。構造体にはアライメント(メモリ配置の都合)のため、メンバとメンバの間に「パディング」と呼ばれる未使用の隙間が入ることがあり、この隙間の中身は不定です。値としては等しい2つの構造体でも、パディング部分のゴミの値が違っていればmemcmpは「違う」と判定してしまいます。安全に比較するには、メンバを1つずつ明示的に比較する関数を書く必要があります。
関連するエラー
- error: assignment of read-only variable の原因と直し方constをつけて宣言した変数に、後から値を代入しようとしたときに出るエラーです。
- error: assignment of read-only location の原因と直し方const int *pのように「指す先が変更不可」なポインタを介して、*pに値を書き込もうとしたときに出るエラーです。