演算子の不適切な利用によって、次のようなエラーが発生することがある。
f % f; // Invalid operands to binary expression ('float' and 'float')
a + b; // Invalid operands to binary expression ('struct Number' and 'struct Number')
a == b; // Invalid operands to binary expression ('struct Number' and 'struct Number')
const char *s = "a" + "b"; // Invalid operands to binary expression ('const char *' and 'const char *')
これらのエラーは無効な演算が行われていることを表している。実数型と構造体型、文字列型でそれぞれ異なる原因と対処が考えられる。
目次
文字列型の場合
C言語の文字列は+
演算子による連結が行えない。
const char *s = "a" + "b"; // error: invalid operands to binary expression ('const char *' and 'const char *')
const char *s = "a";
s = s + "b"; // error: invalid operands to binary expression ('const char *' and 'const char *')
puts(s + "b"); // error: invalid operands to binary expression ('const char *' and 'const char *')
C言語の文字列は手動で連結しなければならない。以下の記事を参考にされたい。
参考:C言語の文字列を連結する方法
実数型の場合
原因
実数型(浮動小数点数型)に対応していない演算子が用いられていると、このようなエラーが発生する原因となる。とりわけfloat型やdouble型の余剰やビット演算の利用で本エラーが発生する。
double d = 9;
d << 1; // Invalid operands to binary expression ('double' and 'int')
d >> 1; // Invalid operands to binary expression ('double' and 'int')
d ^ d; // Invalid operands to binary expression ('double' and 'double')
d & d; // Invalid operands to binary expression ('double' and 'double')
~d; // Invalid argument type 'double' to unary expression
!d; // OK
対処方法
浮動小数点数型の余剰を行う場合には、fmod
関数やfmodf
関数を用いる必要がある。fmodはdouble型、fmodfはfloat型の計算に対応している。
// #include <math.h>
// float fmodf(float x, float y);
// double fmod(double x, double y);
double d = 9;
// Before
d % 6;
// After
fmod(d, 6);
fmod関数、fmodf関数、fmodl関数|C言語関数リファレンス
C言語でべき乗を求める場合にはpow関数を用いる必要がある。^
演算子は排他的論理和を求めるための演算子であるため注意したい。
// #include <math.h>
// float powf(float, float);
// double pow(double, double);
// Before
2 ^ 3; // 1(ビット演算が行われてしまう)
// After
pow(2, 3); // 8(べき乗が求められる)
構造体型の場合
原因
構造体同士の比較や演算についても、同様のエラーが発生する。C言語では構造体同士の比較は行えないため注意したい。
struct Number { int value; };
struct Number a = {9}, b = {9};
if (a == b) { puts("same"); } // Invalid operands to binary expression ('struct Number' and 'struct Number')
struct Number c = a + b; // Invalid operands to binary expression ('struct Number' and 'struct Number')
対処方法(C言語/C++)
構造体同士の比較は行えないため、構造体のメンバ変数を個別に比較する必要がある。
struct Number { int value; };
struct Number a = {9}, b = {9};
// メンバ変数の値を比較する
if (a.value == b.value) { puts("same"); }
算術演算を行う場合も同様に、対象のメンバ同士の演算結果を新たな構造体のメンバとして生成する必要がある。
// 演算結果を保持する新たな構造体を宣言する
struct Number c = {a.value + b.value};
assert( c.value == 18 );
struct Number d;
d.value = a.value * b.value;
assert( d.value == 81 );
より詳しい説明は以下の記事が参考になる。
【C言語】構造体を比較する方法
対処方法(C++)
C++の場合は、演算子オーバーロード(演算子の多重定義)を行うことで、構造体同士の比較や演算を実現することができる。
struct Number {
int value;
bool operator==(const Number& x) { return x.value == value; }
Number operator+(const Number& x) { return {x.value == value}; }
};
Number a{9}, b{9};
assert( a == b ); // OK
Number c = a + b;
assert( c.value == 18 ); // OK
より詳しい説明と非メンバ関数による多重定義の方法は以下の記事が参考になる。
【C++】比較演算子の定義