web-dev-qa-db-ja.com

単純に1ではなく、Cブールマクロで#define TRUE(1 == 1)を使用するのはなぜですか?

私はCで定義を見てきました

#define TRUE (1==1)
#define FALSE (!TRUE)

これは必要ですか? TRUEを1として、FALSEを0として定義することの利点は何ですか?

158
user2468316

このアプローチでは、コンパイラがサポートしている場合、実際のboolean型を使用します(そして、trueおよびfalseに解決します)。 (具体的には、C++)

ただし、C++が(__cplusplusマクロを介して)使用されているかどうかを確認し、実際にtruefalseを使用する方が良いでしょう。

Cコンパイラでは、これは0および1と同等です。
(括弧を削除すると、操作の順序により括弧が壊れることに注意してください)

153
SLaks

_(1 == 1)_トリックは、Cに対して透過的な方法でTRUEを定義するのに役立ちますが、C++での入力を改善します。 「Clean C」(CまたはC++としてコンパイル)と呼ばれる方言で記述している場合、またはCまたはC++プログラマーが使用できるAPIヘッダーファイルを記述している場合、同じコードをCまたはC++として解釈できます。

C翻訳単位では、_1 == 1_は_1_とまったく同じ意味を持ちます。および_1 == 0_は_0_と同じ意味を持ちます。ただし、C++翻訳単位では、_1 == 1_の型はboolです。したがって、そのように定義されたTRUEマクロは、C++により良く統合されます。

統合方法の例として、たとえば、関数foointboolのオーバーロードを持っている場合、foo(TRUE)boolオーバーロード。 TRUEが_1_として定義されている場合、C++ではうまく機能しません。 foo(TRUE)intオーバーロードが必要です。

もちろん、C99はbooltrue、およびfalseを導入し、これらはC99およびCで動作するヘッダーファイルで使用できます。

しかしながら:

  • TRUEおよびFALSEを_(0==0)_および_(1==0)_として定義するこの慣行は、C99よりも前です。
  • c99から離れてC90で作業することには、まだ十分な理由があります。

CとC++の混合プロジェクトで作業しており、C99が必要ない場合は、代わりに小文字のtruefalseおよびboolを定義します。

_#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif
_

とはいえ、_0==0_トリックは、C++との相互運用を意図していないコードでも、一部のプログラマーによって使用されています(is?)。 これは何も買わず、プログラマーがCでブール値がどのように機能するかについて誤解していることを示唆しています


C++の説明が明確でない場合、テストプログラムは次のとおりです。

_#include <cstdio>

void foo(bool x)
{
   std::puts("bool");  
}

void foo(int x)
{
   std::puts("int");  
}

int main()
{
   foo(1 == 1);
   foo(1);
   return 0;
}
_

出力:

_bool
int
_

CとC++の混合プログラミングに関連するオーバーロードされたC++関数のコメントからの質問について。これらは型の違いを示しています。 C++としてコンパイルしたときにtrue定数をboolにしたい正当な理由は、クリーンな診断のためです。最高の警告レベルでは、整数をboolパラメーターとして渡すと、C++コンパイラーが変換について警告する場合があります。 Clean Cで記述する理由の1つは、コードがより移植性があること(CコンパイラだけでなくC++コンパイラでも理解されるため)だけでなく、C++コンパイラの診断意見から利益を得ることができるからです。

50
Kaz
_#define TRUE (1==1)
#define FALSE (!TRUE)
_

と同等です

_#define TRUE  1
#define FALSE 0
_

cで.

関係演算子の結果は_0_または_1_です。 _1==1_は_1_に評価されることが保証され、!(1==1)は_0_に評価されることが保証されます。

最初の形式を使用する理由はまったくありません。ただし、ほとんどすべてのコンパイラーでは定数式が実行時ではなくコンパイル時に評価されるため、最初の形式の効率は低下しません。これは、次の規則に従って許可されます。

(C99、6.6p2)「定数式は、実行時ではなく翻訳中に評価できるため、定数が存在する可能性のあるあらゆる場所で使用できます。」

TRUEおよびFALSEマクロにリテラルを使用しない場合、PC-Lintはメッセージ(506、定数値ブール値)を発行します。

Cの場合、TRUEは_1_になるように定義する必要があります。ただし、他の言語は1以外の量を使用するため、一部のプログラマーは_!0_が安全にプレイしていると感じています。

また、C99では、ブールマクロtrueおよびfalseの_stdbool.h_定義は、リテラルを直接使用します。

_#define true   1
#define false  0
_
18
ouah

C++(既に述べた)とは別に、もう1つの利点は静的分析ツールです。コンパイラーは非効率性を排除しますが、静的アナライザーは独自の抽象型を使用して比較結果と他の整数型を区別できるため、TRUEは比較の結果でなければならず、互換性があると見なされるべきではないことを暗黙的に認識します整数で。

明らかにCは互換性があると言っていますが、バグを強調するためにその機能の意図的な使用を禁止することもできます。たとえば、誰かが混乱する場合は&および&&、または、演算子の優先順位を下げました。

12
sh1

実際の違いはありません。 0falseに評価され、1trueに評価されます。 ブール式1 == 1)または1を使用してtrueを定義するという事実は、違いはありません。両方ともintに評価されます。

C標準ライブラリは、ブール値を定義する特定のヘッダーstdbool.hを提供していることに注意してください。

3
Shoe

TRUEが等しい正確な値はわかりません。コンパイラは独自の定義を持つことができます。したがって、privodeは、コンパイラの内部定義を使用して定義します。これは、プログラミングの習慣が優れている場合には必ずしも必要ではありませんが、コーディングスタイルが悪い場合の問題を回避できる場合があります。例:

if((a> b)== TRUE)

TRUEの内部値が別の値であるのに、手動でTRUEを1として定義すると、これは災害になる可能性があります。

3
capiggue
  1. リストアイテム

通常、Cプログラミング言語では、1はtrueとして定義され、0はfalseとして定義されます。したがって、次のことが頻繁に表示される理由:

#define TRUE 1 
#define FALSE 0

ただし、0以外の数値は、条件文でもtrueと評価されます。したがって、以下を使用して:

#define TRUE (1==1)
#define FALSE (!TRUE)

Falseをtrueではないものと等しくすることで、安全にプレイしようとしていることを明示的に示すことができます。

2