11

多くのグーグル検索の後でも、Cの定数式とそうでないものとの間で少し混乱しています。C の定数式とそうでないものの例を教えてください。

4

6 に答える 6

18

A constant expression can be evaluated at compile time. That means it has no variables in it. For example:

5 + 7 / 3

is a constant expression. Something like:

5 + someNumber / 3

is not, assuming someNumber is a variable (ie, not itself a compile-time constant).

于 2010-09-20T21:11:30.047 に答える
15

定数式には別の微妙な点があります。コンパイラにはわかっていても、プリプロセッサにはわからないことがあります。

たとえば(24*60*60)、両方で計算できますがsizeof struct foo、コンパイラだけが知っています。この区別は、 astructが外部で指定されたサイズを満たすように定義されていること、またはそのメンバーが外部で指定されたオフセットにマップされていることを確認しようとしている場合に重要になります。struct(この使用例は、デバイス レジスタがメモリ空間に配置されていると記述されているデバイス ドライバをコーディングするときによく発生します。)

その場合#if (sizeof(struct UART) == 12)、プリプロセッサはコンパイルの前のパスで動作し、型のサイズを単純に知ることができないため、単純に言うことはできません。ただし、これは定数式であり、グローバル変数の初期化子として (例: int UARTwords = sizeof(struct UART) / sizeof(short);)、または配列のサイズを宣言するために(例: unsigned char UARTmirror[sizeof(struct UART)];)有効です。

于 2010-09-20T21:22:48.317 に答える
5

さらに別の種類の定数式であるアドレス定数については誰も言及していないようです。静的ストレージ期間を持つオブジェクトのアドレスはアドレス定数であるため、ファイルスコープでこの種のことを行うことができます:

char x;
char *p = &x;

文字列リテラルは、静的な保存期間を持つ配列を定義するため、このルールは、ファイル スコープでこれを実行できる理由でもあります。

char *s = "foobar";
于 2010-09-21T00:27:30.170 に答える
3

単一値リテラルは定数式です。

3     0.0f    '\n'

(文字列リテラルは、実際には配列であるため、奇妙です。最終"hello"的にリンクする必要があり、アドレスと内容が実行時に変更される可能性があるため、実際には定数ではないようです。)

定数または型に適用されるほとんどの演算子 (sizeof、キャストなど) は定数式です。

sizeof(char)
(byte) 15

定数式のみを含む式は、それ自体も定数式です。

15 + 3
0.0f + 0.0f
sizeof(char)

関数呼び出しまたは非定数式を含む式は、通常、定数式ではありません

strlen("hello")
fifteen + x

定数式としてのマクロのステータスは、展開先によって異なります。

/* Always a constant */
#define FIFTEEN 15

/* Only constant if (x) is
#define htons(x)  (( ((x) >> 8) | ((x) << 8) ) & 0xffff) 

/* Never constant */
#define X_LENGTH  strlen(x)

私はもともと識別子についてここにいくつかのものを持っていましたconstが、それをテストしたところ、明らかにCには適用されません。 奇妙なことに、定数を宣言していません(少なくとも、ステートメントconstで使用するのに十分な「定数」ではありません)。switchただし、C++ ではそうです。

于 2010-09-20T21:26:34.103 に答える
2

もう1つの楽しい小さなしわ:Cでは、「enum」の値は定数ですが、「enum」の宣言が完了した後にのみ使用できます。たとえば、以下は標準Cでは受け入れられませんが、C++では受け入れられます。

列挙型{foo=19、bar、boz = bar + 5;};

書き直すことができます:

列挙型{foo=19、bar}; 列挙型{boz=bar + 5;};

ただし、これにより、すべての値を保持する列挙型ではなく、複数の異なる列挙型が定義されることになります。

于 2010-09-20T21:44:42.280 に答える
2

またintegral character constants'a'またはは'\n'コンパイラがそのように認識する定数です。タイプがありintます。

于 2010-09-20T22:06:36.193 に答える