質問
私は、多くのGoogleingの後であっても、Cでの一定の表現ではないものの間で少し混乱しています。 Cの一定の式であるものの例を提供できますか?
解決
コンパイル時に一定の式を評価できます。つまり、変数がないことを意味します。例えば:
5 + 7 / 3
一定の式です。何かのようなもの:
5 + someNumber / 3
想定していません someNumber
変数です(つまり、それ自体はコンパイル時定数ではありません)。
他のヒント
一定の表現には別の微妙さがあります。コンパイラに知られているものがいくつかありますが、プリプロセッサには知られていません。
例えば (24*60*60)
両方で計算できますが sizeof struct foo
コンパイラにのみ知られています。あなたがそれを確認しようとしている場合、この区別は重要です struct
外部から義務付けられたサイズを満たすか、そのメンバーが外部指定されたオフセットでマッピングされることを定義します。 (このユースケースは、デバイスドライバーをコーディングするときにしばしば発生します。 struct
メモリスペースにレイアウトされているデバイスレジスタについて説明します。
その場合、単純に言うことはできません #if (sizeof(struct UART) == 12)
プリプロセッサは、コンピレーションの前のパスで動作し、あらゆるタイプのサイズを単純に知ることができないためです。ただし、それは一定の式であり、グローバル変数の初期イザーとして有効です(例: int UARTwords = sizeof(struct UART) / sizeof(short);
)、または配列のサイズを宣言する(例: unsigned char UARTmirror[sizeof(struct UART)];
)
誰も、さらに別の種類の一定の式:アドレス定数について言及しているようです。静的ストレージ期間のオブジェクトのアドレスはアドレス定数です。したがって、ファイルスコープでこの種のことを行うことができます。
char x;
char *p = &x;
文字列リテラルは、静的ストレージ期間で配列を定義するため、このルールはファイルスコープでこれを行うことができる理由でもあります。
char *s = "foobar";
単一値のリテラルは、一定の表現です。
3 0.0f '\n'
(文字列リテラルは実際には配列なので、奇妙です。 "hello"
リンクされなければならないので、実際には一定ではありません。
定数またはタイプに適用されるほとんどのオペレーター(サイズ、キャストなど)は一定の式です。
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 ++では、そうです。
別の楽しい小さなしわ:Cでは、「列挙」の値は定数ですが、「列挙」の宣言が完了した後にのみ使用できます。たとえば、以下は標準Cでは受け入れられませんが、C ++では受け入れられます。
enum {foo=19, bar, boz=bar+5;};
書き直すことができます:
enum {foo=19, bar}; enum {boz=bar+5;};
ただし、これは、すべての値を保持するものではなく、複数の異なる列挙タイプを定義することになります。
また integral character constants
なので 'a'
また '\n'
コンパイラがそのように認識する定数です。タイプがあります int
.