Example of something which is, and is not, a “Cons

2019-01-19 02:14发布

I'm a tad confused between what is and is not a Constant Expression in C, even after much Googleing. Could you provide an example of something which is, and which is not, a Constant Expression in C?

6条回答
够拽才男人
2楼-- · 2019-01-19 02:21

Nobody seems have mentioned yet another kind of constant expression: address constants. The address of an object with static storage duration is an address constant, hence you can do this kind of thing at file scope:

char x;
char *p = &x;

String literals define arrays with static storage duration, so this rule is also why you can do this at file scope:

char *s = "foobar";
查看更多
ら.Afraid
3楼-- · 2019-01-19 02:24

Another fun little wrinkle: in C, the value of an 'enum' is a constant, but may only be used after the declaration of the 'enum' is complete. The following, for example, is not acceptable in standard C, though it is acceptable in C++:

enum {foo=19, bar, boz=bar+5;};

It could be rewritten:

enum {foo=19, bar}; enum {boz=bar+5;};

though this would end up defining multiple different enumeration types, rather than one which holds all the values.

查看更多
仙女界的扛把子
4楼-- · 2019-01-19 02:37

There is another subtlety to constant expressions. There are some things that are known to the compiler, but cannot be known to the preprocessor.

For example (24*60*60) can be computed by both, but sizeof struct foo is only known to the compiler. This distinction can matter if you are trying to verify that a struct is defined to meet an externally mandated size, or that its members are mapped at externally specified offsets. (This use case often arises when coding device drivers where the struct describes device registers as layed out in memory space.)

In that instance you cannot simply say #if (sizeof(struct UART) == 12) because the preprocessor operates at a pass ahead of the compilation and simply cannot know the size of any types. It is, however, a constant expression and would be valid as an initializer for a global variable (e.g. int UARTwords = sizeof(struct UART) / sizeof(short);), or to declare the size of an array (e.g. unsigned char UARTmirror[sizeof(struct UART)];)

查看更多
看我几分像从前
5楼-- · 2019-01-19 02:41

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).

查看更多
仙女界的扛把子
6楼-- · 2019-01-19 02:44

Also integral character constants as 'a' or '\n' are constants that the compiler recognizes as such. They have type int.

查看更多
Animai°情兽
7楼-- · 2019-01-19 02:46

Any single-valued literal is a constant expression.

3     0.0f    '\n'

(String literals are weird, because they're actually arrays. Seems "hello" isn't really a constant, as it ends up having to be linked and all that, and the address and contents can change at runtime.)

Most operators (sizeof, casts, etc) applied to constants or types are constant expressions.

sizeof(char)
(byte) 15

Any expression involving only constant expressions is itself also a constant expression.

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

Any expression involving function calls or non-constant expressions is usually not a constant expression.

strlen("hello")
fifteen + x

Any macro's status as a constant expression depends on what it expands to.

/* 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)

I originally had some stuff in here about const identifiers, but i tested that and apparently it doesn't apply in C. const, oddly enough, doesn't declare constants (at least, not ones "constant" enough to be used in switch statements). In C++, however, it does.

查看更多
登录 后发表回答