web-dev-qa-db-ja.com

Cプリプロセッサは整数演算を実行できますか?

質問が言うように、[〜#〜] c [〜#〜]プリプロセッサはそれを実行できますか?

例えば。:

#define PI 3.1416
#define OP PI/100
#define OP2 PI%100

前処理フェーズでOPやOP2を計算する方法はありますか?

24
Schim

整数演算?次のプログラムを実行して調べます。

_#include "stdio.h"
int main() {
    #if 1 + 1 == 2
        printf("1+1==2\n");
    #endif
    #if 1 + 1 == 3
        printf("1+1==3\n");
    #endif
 }
_

答えは「はい」です。プリプロセッサに整数演算を実行させる方法があります。これは、プリプロセッサ条件でそれを使用することです。

ただし、例は整数演算ではないことに注意してください。チェックしたところ、フロート比較を実行しようとすると、gccのプリプロセッサが失敗します。標準がプリプロセッサで浮動小数点演算を許可するかどうかは確認していません。

通常のマクロ展開は整数式を評価せず、コンパイラに任せます。これは、次の前処理(gccの-E)で確認できます。

_#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
    int i = ONEPLUSONE;
#endif
_

結果はint i = (1 + 1);になります(さらに、ソースファイル名や行番号などを示すための要素も含まれます)。

34
Steve Jessop

あなたが書いたコードは、実際にはプリプロセッサに計算をさせません。 #defineは単純なテキスト置換を行うため、次のように定義されています。

#define PI 3.1416
#define OP PI/100

このコード:

if (OP == x) { ... }

なる

if (3.1416/100 == x) { ... }

そして、それはコンパイルされます。コンパイラは、そのような式を取得してコンパイル時に計算し、これと同等のコードを生成することを選択できます。

if (0.031416 == x) { ... }

しかし、これはコンパイラーであり、プリプロセッサーではありません。

あなたの質問に答えるために、はい、プリプロセッサはいくつかの演算を行うことができます。これは、次のように書くと確認できます。

#if (3.141/100 == 20)
   printf("yo");
#Elif (3+3 == 6)
   printf("hey");
#endif
19
shoosh

はい、Boost Preprocessorで実行できます。また、純粋なCと互換性があるため、CのみのコンパイルでCプログラムで使用できます。ただし、コードには浮動小数点数が含まれるため、間接的に行う必要があると思います。

#include <boost/preprocessor/arithmetic/div.hpp>
BOOST_PP_DIV(11, 5) // expands to 2
#define KB 1024
#define HKB BOOST_PP_DIV(A,2)
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B)))
#define RKB REM(KB,2)

int div = HKB;
int rem = RKB;

これは前処理(gcc -Sで確認)

int div = 512;
int rem = 0;

おかげで このスレッド

7
highBandWidth

[〜#〜]はい[〜#〜]、つまり、算術演算を実行できます:)

99本のビール で示されるように。

7
pmg

はい。

特定の難読化されたCコンテストの優勝者にまだ誰もリンクしていないとは信じられません。男は再帰的インクルードを介してプリプロセッサにALUを実装しました。 ここ は実装で、 ここ は説明の一部です。

さて、それはあなたがその男がやったことをしたくないと言いました。それはすべて楽しいですが、彼のヒントファイルでコンパイル時間を確認してください(結果のコードがメンテナンスできないという事実は言うまでもありません)。より一般的には、人々はプリプロセッサをテキストの置換に厳密に使用し、定数整数演算の評価はコンパイル時または実行時に行われます。

ただし、他の人が指摘したように、#ifステートメントでいくつかの演算を行うことができます。

4
Stephen Canon

算術を行うときは注意してください:括弧を追加

#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8

次のようなものを使用した場合:

unsigned int i = TOTALSIZE/4;

そして、iが3であることを期待すると、代わりに4 + 2 = 6になります。括弧を追加:

#define TOTALSIZE (SIZE4 + SIZE8)
2
Phil